* [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers
@ 2026-09-03 13:53 Prashant Gupta
2026-09-03 13:53 ` [PATCH 01/45] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta
` (50 more replies)
0 siblings, 51 replies; 356+ messages in thread
From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw)
To: stephen, dev
This series brings the NXP DPAA2 driver stack up to date with the
functionality carried in the NXP internal tree, together with a number of
bug fixes. It covers the crypto (dpaa2_sec), net, dma, mempool, event and
bus/fslmc drivers.
Fixes first, then features, so the bug fixes can be picked independently of
the larger reworks.
Bug fixes (patches 1-2, 7-11):
- crypto/dpaa2_sec: buffer overflow in GCM decrypt, and an FLE pool leak
on the sec FD build failure path
- dpaa2 device double free on uninit
- integer overflow in the CCSR region mapping
- array-bounds warning in the dma dequeue path
- IOVA validation in the dma pre-populate helpers, which previously
called rte_panic() on an unmapped address and now returns an error
to the caller
- bus/fslmc: bus initialization deferred to probe
Crypto (patches 3-6):
- AES-GMAC support, AES-CTR ivsize range, a missing ECN capability, and
support for configuration via environment variables
Flow and classification (patches 18-24, 35-37):
- MPLS and PPPoE distribution, meter and policing, flow drop action, a
per-device default flow miss action, Rx hash identification by FLC, a
minimum key size, an updated MC dpni QoS/flow-steering API, and a rework
of the flow engine
Datapath and queue management (patches 12-17, 25-34, 38-45):
- dma context index ring enqueue optimization and a bypass
memory-translation option
- Tx queue/channel mapping optimization, Tx confirmation rework, larger
burst sizes, batched DQRR consumption, per-traffic-class Rx mempools and
Rx CGIDs, parser restructuring plus tunnel and fragmented packet type
parsing, PTP enhancements, xstats rework, and removal of the unused soft
parser code
Please note two points that need reviewer input:
1. Patch 3 ("crypto/dpaa2_sec: support AES-GMAC") adds a new public enum
value, RTE_CRYPTO_AEAD_AES_GMAC, to lib/cryptodev/rte_crypto_sym.h. It
is appended at the end of enum rte_crypto_aead_algorithm so it is ABI
compatible, but it is a cryptodev API addition rather than a
driver-local change, so it needs cryptodev maintainer review. The
series does not add a release notes entry for it; I am happy to add
one, or to split that hunk into its own cryptodev patch, whichever is
preferred.
2. Patch 10 ("bus/fslmc: defer bus initialization to probe") carries a
Fixes: tag but no Cc: stable@dpdk.org, because it changes bus
initialization ordering and is more invasive than a targeted fix. Please
advise if it should still be marked for backport.
Testing:
- checkpatches.sh and check-git-log.sh are clean over all 45 patches
- build tested with the dpaa/dpaa2 driver set enabled, no new compiler
warnings
The dpaa2 driver documentation is not updated in this series; the new
features are not yet described in doc/guides. I plan to follow up with a
documentation patch unless reviewers would rather see it folded in here.
Gagandeep Singh (20):
crypto/dpaa2_sec: fix buffer overflow in GCM decrypt
crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure
crypto/dpaa2_sec: support AES-GMAC
crypto/dpaa2_sec: increase ivsize range for AES-CTR
crypto/dpaa2_sec: add missing ECN capability
crypto/dpaa2_sec: add support for env variables
drivers: fix double free of dpaa2 device on uninit
dma/dpaa2: validate IOVA in pre-populate helpers
dma/dpaa2: optimize context index ring enqueue
drivers: add dpaa2 DMA bypass memory translation option
net/dpaa2: set Tx confirmation on device init
drivers: optimize dpaa2 Tx queue and channel mapping
net/dpaa2: support larger burst size
net/dpaa2: support MPLS and PPPoE flow distribution
net/dpaa2: support meter and policing
net/dpaa2: support flow drop action
net/dpaa2: set default flow miss action per device
net/dpaa2: identify Rx mbuf hash information by FLC
net/dpaa2: enhance xstat implementation
net/dpaa2: do not overwrite mbuf hash with drop priority
Hemant Agrawal (9):
net/dpaa2: fix integer overflow in CCSR region mapping
net/dpaa2: add minimum key size support
net/dpaa2: restructure dpaa2 parser processing
net/dpaa2: parse tunnel and fragmented packet types
net/dpaa2: remove unused soft parser Tx code
net/dpaa2: update MC dpni QoS and flow steering API
net/dpaa2: rework flow engine
bus/fslmc: reduce probe-time logging and MC traffic
net/dpaa2: reject Rx queue deferred start
Jun Yang (14):
dma/dpaa2: fix array-bounds warning in dequeue path
mempool/dpaa2: support ops index from primary in secondary
net/dpaa2: remove unused soft parser driver
drivers: refresh dpaa2 MC and SoC version info
drivers: identify dpaa2 soft parser protocol
drivers: assign dpaa2 Rx CGID per traffic class
drivers: inherit dpaa2 rxq config for event queue
net/dpaa2: rename Rx queue flags
drivers: rework dpaa2 Tx confirmation
net/dpaa2: ptp enhancements
net/dpaa2: support Rx mempool per traffic class
drivers: consume dpaa2 DQRR entries in batches
drivers: resolve dpaa2 endpoint in the net driver
drivers: align dpaa2 event port depths with hardware rings
Prashant Gupta (2):
bus/fslmc: defer bus initialization to probe
net/dpaa2: read MC version from device private data
drivers/bus/fslmc/bus_fslmc_driver.h | 15 +-
drivers/bus/fslmc/fslmc_bus.c | 185 +-
drivers/bus/fslmc/fslmc_vfio.c | 196 +-
drivers/bus/fslmc/fslmc_vfio.h | 30 +-
drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 83 +-
drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 7 -
drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 45 +-
drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 7 +-
drivers/bus/fslmc/private.h | 3 +
.../fslmc/qbman/include/fsl_qbman_portal.h | 12 +-
drivers/bus/fslmc/qbman/qbman_portal.c | 78 +-
drivers/bus/fslmc/qbman/qbman_portal.h | 11 +-
drivers/common/dpaax/rte_pmd_dpaax_qdma.h | 4 +-
drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 50 +-
drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 45 +-
drivers/dma/dpaa2/dpaa2_qdma.c | 162 +-
drivers/dma/dpaa2/dpaa2_qdma.h | 1 +
drivers/event/dpaa2/dpaa2_eventdev.c | 76 +-
drivers/event/dpaa2/dpaa2_eventdev.h | 4 +-
drivers/mempool/dpaa2/dpaa2_hw_mempool.c | 88 +-
drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 546 --
drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +-
drivers/net/dpaa2/dpaa2_ethdev.c | 2142 +++--
drivers/net/dpaa2/dpaa2_ethdev.h | 755 +-
drivers/net/dpaa2/dpaa2_flow.c | 6933 ++++++++++-------
drivers/net/dpaa2/dpaa2_meter.c | 588 ++
drivers/net/dpaa2/dpaa2_parse_dump.h | 374 -
drivers/net/dpaa2/dpaa2_parser_decode.h | 1539 ++++
drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 +
drivers/net/dpaa2/dpaa2_ptp.c | 176 +-
drivers/net/dpaa2/dpaa2_recycle.c | 37 +-
drivers/net/dpaa2/dpaa2_rxtx.c | 1903 ++---
drivers/net/dpaa2/dpaa2_sparser.c | 137 -
drivers/net/dpaa2/dpaa2_sparser.h | 202 -
drivers/net/dpaa2/dpaa2_tm.c | 16 +-
drivers/net/dpaa2/mc/dpni.c | 138 +-
drivers/net/dpaa2/mc/fsl_dpni.h | 390 +-
drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 33 +-
drivers/net/dpaa2/meson.build | 5 +-
lib/cryptodev/rte_crypto_sym.h | 2 +
40 files changed, 10537 insertions(+), 6554 deletions(-)
delete mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni.c
create mode 100644 drivers/net/dpaa2/dpaa2_meter.c
delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h
create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h
delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c
delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h
base-commit: 9231dc7c072223628a81f5c755796d95230a5572
--
2.43.0
^ permalink raw reply [flat|nested] 356+ messages in thread* [PATCH 01/45] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 02/45] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure Prashant Gupta ` (49 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> In build_authenc_gcm_fd, when both AAD (auth_only_len > 0) and decrypt direction are active, the SGE layout occupies 8 entries plus 16 bytes of old_icv storage at index 8. The FLE pool buffer was only 256 bytes (8 x 32), causing old_icv to be written one entry past the end of the allocated buffer. The resulting virtual address was not mapped by the IOMMU, so DPAA2_VADDR_TO_IOVA returned 0 and the SEC engine received iova=0x00000000 as the ICV buffer address, triggering an SMMU translation fault (FSR=0x402 TF). Additionally, the upfront bpid/IVP initialization only covered sge+3, leaving sge+4 (the input data SGE when AAD is present) without a valid bpid or IVP assignment. Increase FLE_POOL_BUF_SIZE from 256 to 288 (9 x 32 bytes) to accommodate the full layout, and extend the bpid/IVP initialization to cover sge+4 in both branches of build_authenc_gcm_fd. Fixes: 13273250eec5 ("crypto/dpaa2_sec: support AES-GCM and CTR") Cc: stable@dpdk.org Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 2 ++ drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 3d980d096f..2a015a3d82 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -569,6 +569,7 @@ build_authenc_gcm_fd(dpaa2_sec_session *sess, DPAA2_SET_FLE_BPID(sge + 1, bpid); DPAA2_SET_FLE_BPID(sge + 2, bpid); DPAA2_SET_FLE_BPID(sge + 3, bpid); + DPAA2_SET_FLE_BPID(sge + 4, bpid); } else { DPAA2_SET_FD_IVP(fd); DPAA2_SET_FLE_IVP(fle); @@ -577,6 +578,7 @@ build_authenc_gcm_fd(dpaa2_sec_session *sess, DPAA2_SET_FLE_IVP((sge + 1)); DPAA2_SET_FLE_IVP((sge + 2)); DPAA2_SET_FLE_IVP((sge + 3)); + DPAA2_SET_FLE_IVP((sge + 4)); } /* Save the shared descriptor */ diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index 755c8e9cc3..ff32f3d860 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -17,7 +17,7 @@ extern uint8_t cryptodev_driver_id; /* FLE_POOL_NUM_BUFS is set as per the ipsec-secgw application */ #define FLE_POOL_NUM_BUFS 32000 -#define FLE_POOL_BUF_SIZE 256 +#define FLE_POOL_BUF_SIZE 288 #define FLE_POOL_CACHE_SIZE 512 #define FLE_SG_MEM_SIZE(num) (FLE_POOL_BUF_SIZE + ((num) * 32)) -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 02/45] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta 2026-09-03 13:53 ` [PATCH 01/45] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 03/45] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta ` (48 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> When build_sec_fd fails at index loop inside the enqueue burst loops, the previously built FD entries (indices 0..loop-1) were never freed. The cleanup loop iterated in the wrong direction, starting at the failed index and going up to frames_to_send, which are entries that were never built. This caused silent FLE pool exhaustion, after which every subsequent build_sec_fd returned -ENOMEM, enqueue_burst returned 0 indefinitely, and the crypto-perf test hung. Fix both dpaa2_sec_enqueue_burst and dpaa2_sec_enqueue_burst_ordered by clamping frames_to_send to loop + 1 and iterating from 0 to free all allocated FLE buffers including the failed entry. Fixes: 623326dded3a ("crypto/dpaa2_sec: introduce poll mode driver") Cc: stable@dpdk.org Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 2a015a3d82..15152cc5a1 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1550,6 +1550,9 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, ret = build_sec_fd(*ops, &fd_arr[loop], bpid, dpaa2_qp); if (ret) { DPAA2_SEC_DP_DEBUG("FD build failed"); + frames_to_send = loop + 1; + for (loop = 0; loop < frames_to_send; loop++) + free_fle(&fd_arr[loop], dpaa2_qp); goto skip_tx; } ops++; @@ -1909,6 +1912,9 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, ret = build_sec_fd(*ops, &fd_arr[loop], bpid, dpaa2_qp); if (ret) { DPAA2_SEC_DP_DEBUG("FD build failed"); + frames_to_send = loop + 1; + for (loop = 0; loop < frames_to_send; loop++) + free_fle(&fd_arr[loop], dpaa2_qp); goto skip_tx; } ops++; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 03/45] crypto/dpaa2_sec: support AES-GMAC 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta 2026-09-03 13:53 ` [PATCH 01/45] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta 2026-09-03 13:53 ` [PATCH 02/45] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 04/45] crypto/dpaa2_sec: increase ivsize range for AES-CTR Prashant Gupta ` (47 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Akhil Goyal, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add AES-GMAC as a supported AEAD algorithm for IPsec protocol offload. AES-GMAC provides NULL encryption with GMAC authentication and maps to OP_PCL_IPSEC_AES_NULL_WITH_GMAC in the SEC protocol control word. When AES_GMAC is specified as an AUTH (non-AEAD) algorithm, return -ENOTSUP with an informative message directing the user to the AEAD path. Add RTE_CRYPTO_AEAD_AES_GMAC to the AEAD algorithm enum and expose the capability in dpaa2_sec_capabilities. Signed-off-by: Akhil Goyal <gakhil@marvell.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 15 +++++++++- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 33 ++++++++++++++++++++- lib/cryptodev/rte_crypto_sym.h | 2 ++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 15152cc5a1..0e4e67aa07 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ @@ -2975,6 +2975,13 @@ dpaa2_sec_ipsec_aead_init(struct rte_crypto_aead_xform *aead_xform, aeaddata->algmode = OP_ALG_AAI_CCM; session->aead_alg = RTE_CRYPTO_AEAD_AES_CCM; break; + case RTE_CRYPTO_AEAD_AES_GMAC: + /** + * AES-GMAC is an AEAD algo with NULL encryption and GMAC + * authentication. + */ + aeaddata->algtype = OP_PCL_IPSEC_AES_NULL_WITH_GMAC; + break; default: DPAA2_SEC_ERR("Crypto: Undefined AEAD specified %u", aead_xform->algo); @@ -3046,6 +3053,10 @@ dpaa2_sec_ipsec_proto_init(struct rte_crypto_cipher_xform *cipher_xform, authdata->algtype = OP_PCL_IPSEC_HMAC_MD5_96; authdata->algmode = OP_ALG_AAI_HMAC; break; + case RTE_CRYPTO_AUTH_AES_GMAC: + DPAA2_SEC_ERR( + "AES_GMAC is supported as AEAD algo for IPSEC proto only"); + return -ENOTSUP; case RTE_CRYPTO_AUTH_SHA224_HMAC: authdata->algmode = OP_ALG_AAI_HMAC; if (session->digest_length == 6) @@ -3217,6 +3228,7 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev, case OP_PCL_IPSEC_AES_GCM8: case OP_PCL_IPSEC_AES_GCM12: case OP_PCL_IPSEC_AES_GCM16: + case OP_PCL_IPSEC_AES_NULL_WITH_GMAC: memcpy(encap_pdb.gcm.salt, (uint8_t *)&(ipsec_xform->salt), 4); break; @@ -3357,6 +3369,7 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev, case OP_PCL_IPSEC_AES_GCM8: case OP_PCL_IPSEC_AES_GCM12: case OP_PCL_IPSEC_AES_GCM16: + case OP_PCL_IPSEC_AES_NULL_WITH_GMAC: memcpy(decap_pdb.gcm.salt, (uint8_t *)&(ipsec_xform->salt), 4); break; diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index ff32f3d860..1824cc4a60 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2020-2024 NXP + * Copyright 2016,2020-2026 NXP * */ @@ -762,6 +762,37 @@ static const struct rte_cryptodev_capabilities dpaa2_sec_capabilities[] = { }, } }, } }, + { /* AES GMAC (AEAD) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD, + {.aead = { + .algo = RTE_CRYPTO_AEAD_AES_GMAC, + .block_size = 16, + .key_size = { + .min = 16, + .max = 32, + .increment = 8 + }, + .digest_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .aad_size = { + .min = 0, + .max = 65535, + .increment = 1 + }, + .iv_size = { + .min = 12, + .max = 16, + .increment = 4 + } + }, } + }, } + }, + RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() }; diff --git a/lib/cryptodev/rte_crypto_sym.h b/lib/cryptodev/rte_crypto_sym.h index 630fd153bd..f65db616a0 100644 --- a/lib/cryptodev/rte_crypto_sym.h +++ b/lib/cryptodev/rte_crypto_sym.h @@ -508,6 +508,8 @@ enum rte_crypto_aead_algorithm { /**< AES algorithm in NCA5 mode */ RTE_CRYPTO_AEAD_ZUC_NCA6, /**< ZUC-256 algorithm in NCA6 mode */ + RTE_CRYPTO_AEAD_AES_GMAC, + /**< AES algorithm in GMAC mode. */ }; /** Symmetric AEAD Operations */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 04/45] crypto/dpaa2_sec: increase ivsize range for AES-CTR 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (2 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 03/45] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 05/45] crypto/dpaa2_sec: add missing ECN capability Prashant Gupta ` (46 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Widen the AES-CTR IV size range from the fixed 16-byte value to [12, 16] with a 4-byte increment. This allows 96-bit IVs (the standard NIST SP 800-38A recommendation) in addition to 128-bit IVs, aligning with common usage and test-vector expectations. The change applies to both dpaa2_sec_capabilities and dpaa2_pdcp_capabilities. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index 1824cc4a60..7e18e83858 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -625,9 +625,9 @@ static const struct rte_cryptodev_capabilities dpaa2_sec_capabilities[] = { .increment = 8 }, .iv_size = { - .min = 16, + .min = 12, .max = 16, - .increment = 0 + .increment = 4 }, }, } }, } @@ -855,9 +855,9 @@ static const struct rte_cryptodev_capabilities dpaa2_pdcp_capabilities[] = { .increment = 8 }, .iv_size = { - .min = 16, + .min = 12, .max = 16, - .increment = 0 + .increment = 4 } }, } }, } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 05/45] crypto/dpaa2_sec: add missing ECN capability 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (3 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 04/45] crypto/dpaa2_sec: increase ivsize range for AES-CTR Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 06/45] crypto/dpaa2_sec: add support for env variables Prashant Gupta ` (45 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Set the .ecn = 1 flag in both tunnel-mode security capability entries to advertise that the driver supports ECN (Explicit Congestion Notification) copying during IPsec encap/decap. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index 7e18e83858..16b8273a79 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -1004,6 +1004,7 @@ static const struct rte_security_capability dpaa2_sec_security_cap[] = { .copy_df = 1, .copy_dscp = 1, .dec_ttl = 1, + .ecn = 1, .esn = 1, }, .replay_win_sz_max = 1024 @@ -1023,6 +1024,7 @@ static const struct rte_security_capability dpaa2_sec_security_cap[] = { .copy_df = 1, .copy_dscp = 1, .dec_ttl = 1, + .ecn = 1, .esn = 1, }, .replay_win_sz_max = 1024 -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 06/45] crypto/dpaa2_sec: add support for env variables 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (4 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 05/45] crypto/dpaa2_sec: add missing ECN capability Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 07/45] drivers: fix double free of dpaa2 device on uninit Prashant Gupta ` (44 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Allow driver configuration via environment variables as a fallback when devargs are not provided. After processing devargs (or when devargs are absent), check DRIVER_STRICT_ORDER and DRIVER_DUMP_MODE environment variables to set en_loose_ordered and dpaa2_sec_dp_dump. This lets users configure the driver without modifying EAL arguments, useful in environments where command-line access is restricted. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 27 ++++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 0e4e67aa07..c54960820c 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -4379,25 +4379,44 @@ check_devargs_handler(const char *key, const char *value, static void dpaa2_sec_get_devargs(struct rte_cryptodev *cryptodev, const char *key) { + struct dpaa2_sec_dev_private *internals; struct rte_kvargs *kvlist; struct rte_devargs *devargs; + int ret; + char *env; + + internals = cryptodev->data->dev_private; devargs = cryptodev->device->devargs; if (!devargs) - return; + goto env_set; kvlist = rte_kvargs_parse(devargs->args, NULL); if (!kvlist) - return; + goto env_set; if (!rte_kvargs_count(kvlist, key)) { rte_kvargs_free(kvlist); - return; + goto env_set; } - rte_kvargs_process(kvlist, key, + ret = rte_kvargs_process(kvlist, key, check_devargs_handler, (void *)cryptodev); rte_kvargs_free(kvlist); + if (!ret) + return; + +env_set: + env = getenv(DRIVER_STRICT_ORDER); + if (env) + internals->en_loose_ordered = !atoi(env); + + env = getenv(DRIVER_DUMP_MODE); + if (env) { + dpaa2_sec_dp_dump = atoi(env); + if (dpaa2_sec_dp_dump > DPAA2_SEC_DP_FULL_DUMP) + dpaa2_sec_dp_dump = DPAA2_SEC_DP_FULL_DUMP; + } } static int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 07/45] drivers: fix double free of dpaa2 device on uninit 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (5 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 06/45] crypto/dpaa2_sec: add support for env variables Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 14:05 ` David Marchand 2026-09-03 13:53 ` [PATCH 08/45] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (43 subsequent siblings) 50 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> dpaa2_dpdmai_dev_uninit() was called from dpaa2_qdma_close(), but rte_dma close may run without a matching device remove, so the uninitialization (which frees the qdma_dev allocation and the MC portal) could run twice or leak the MC portal. Move dpaa2_dpdmai_dev_uninit() to dpaa2_qdma_remove(), which is the correct teardown counterpart of dpaa2_qdma_probe(). To reach the dmadev from the remove callback, store the rte_dma_dev pointer in struct rte_dpaa2_device at probe time and use it in remove, dropping the now-unused forward declaration. Fixes: 8caf8427f85a ("dma/dpaa2: introduce driver skeleton") Cc: stable@dpdk.org Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 1 + drivers/dma/dpaa2/dpaa2_qdma.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 44f81cf662..c64ef094d0 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -102,6 +102,7 @@ struct rte_dpaa2_device { char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ + struct rte_dma_dev *dmadev; /**< DMA device */ }; typedef int (*rte_dpaa2_obj_create_t)(int vdev_fd, diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index f7d94bb799..4a95f2a1ab 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -1455,9 +1455,6 @@ dpaa2_qdma_stop(struct rte_dma_dev *dev) return 0; } -static int -dpaa2_dpdmai_dev_uninit(struct rte_dma_dev *dev); - static int dpaa2_qdma_close(struct rte_dma_dev *dev) { @@ -1508,8 +1505,6 @@ dpaa2_qdma_close(struct rte_dma_dev *dev) /* Reset QDMA device structure */ qdma_dev->num_vqs = 0; - dpaa2_dpdmai_dev_uninit(dev); - return 0; } @@ -1708,6 +1703,7 @@ dpaa2_qdma_probe(struct rte_dpaa2_driver *dpaa2_drv, return -EINVAL; } + dpaa2_dev->dmadev = dmadev; dmadev->dev_ops = &dpaa2_qdma_ops; dmadev->device = &dpaa2_dev->device; dmadev->fp_obj->dev_private = dmadev->data->dev_private; @@ -1731,10 +1727,13 @@ dpaa2_qdma_probe(struct rte_dpaa2_driver *dpaa2_drv, static int dpaa2_qdma_remove(struct rte_dpaa2_device *dpaa2_dev) { + struct rte_dma_dev *dmadev = dpaa2_dev->dmadev; int ret; DPAA2_QDMA_FUNC_TRACE(); + dpaa2_dpdmai_dev_uninit(dmadev); + ret = rte_dma_pmd_release(dpaa2_dev->device.name); if (ret) DPAA2_QDMA_ERR("Device cleanup failed"); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH 07/45] drivers: fix double free of dpaa2 device on uninit 2026-09-03 13:53 ` [PATCH 07/45] drivers: fix double free of dpaa2 device on uninit Prashant Gupta @ 2026-09-03 14:05 ` David Marchand 0 siblings, 0 replies; 356+ messages in thread From: David Marchand @ 2026-09-03 14:05 UTC (permalink / raw) To: Prashant Gupta; +Cc: stephen, dev, stable, Gagandeep Singh, Hemant Agrawal On Thu, 3 Sept 2026 at 15:55, Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > > From: Gagandeep Singh <g.singh@nxp.com> > > dpaa2_dpdmai_dev_uninit() was called from dpaa2_qdma_close(), but > rte_dma close may run without a matching device remove, so the > uninitialization (which frees the qdma_dev allocation and the MC portal) > could run twice or leak the MC portal. > > Move dpaa2_dpdmai_dev_uninit() to dpaa2_qdma_remove(), which is the > correct teardown counterpart of dpaa2_qdma_probe(). To reach the dmadev > from the remove callback, store the rte_dma_dev pointer in > struct rte_dpaa2_device at probe time and use it in remove, dropping the > now-unused forward declaration. > > Fixes: 8caf8427f85a ("dma/dpaa2: introduce driver skeleton") > Cc: stable@dpdk.org > > Signed-off-by: Gagandeep Singh <g.singh@nxp.com> Nack. I just cleaned this up so maybe it is probably a regression of my change. 868a3abd0ee5 ("dma/dpaa2: remove dmadev pointer from bus device") Thank you. -- David Marchand ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH 08/45] net/dpaa2: fix integer overflow in CCSR region mapping 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (6 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 07/45] drivers: fix double free of dpaa2 device on uninit Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 09/45] dma/dpaa2: fix array-bounds warning in dequeue path Prashant Gupta ` (42 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is defined as sysconf(_SC_PAGESIZE) which may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). Use sysconf() explicitly with a signed long, check for errors, and compute map_len separately with unsigned arithmetic before passing to mmap. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..80c20272ce 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,8 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +185,27 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } start = addr & PAGE_MASK; offset = addr - start; len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + map_len = len & ~(page_size - 1); + if (map_len < (size_t)page_size) + map_len = (size_t)page_size; + + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 09/45] dma/dpaa2: fix array-bounds warning in dequeue path 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (7 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 08/45] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 10/45] bus/fslmc: defer bus initialization to probe Prashant Gupta ` (41 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Jun Yang From: Jun Yang <jun.yang@nxp.com> In dpaa2_qdma_dq_fd, passing a local uint16_t variable directly as a pointer to qdma_cntx_idx_ring_eq caused a compiler array-bounds warning because the function takes a pointer to an element of the ring array. Add a per-queue scratch buffer idxs[DPAA2_QDMA_MAX_DESC] to struct qdma_virt_queue and use idxs[0] instead of a local variable pointer. Also consolidate the fle_sdd pointer assignment for LONG and SG FD types to avoid code duplication. Fixes: 388e888dc082 ("dma/dpaa2: support short FD") Cc: stable@dpdk.org Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/dma/dpaa2/dpaa2_qdma.c | 26 +++++++++----------------- drivers/dma/dpaa2/dpaa2_qdma.h | 1 + 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 4a95f2a1ab..45d7a99805 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -935,35 +935,27 @@ dpaa2_qdma_dq_fd(const struct qbman_fd *fd, enum dpaa2_qdma_fd_type type; int ret; struct qdma_cntx_sg *cntx_sg; - struct qdma_cntx_fle_sdd *fle_sdd; + struct qdma_cntx_fle_sdd *fle_sdd = NULL; att = dpaa2_qdma_fd_get_att(fd); type = DPAA2_QDMA_FD_ATT_TYPE(att); - if (type == DPAA2_QDMA_FD_SHORT) { - idx = DPAA2_QDMA_FD_ATT_CNTX(att); - ret = qdma_cntx_idx_ring_eq(qdma_vq->ring_cntx_idx, - &idx, 1, free_space); - if (unlikely(ret != 1)) - return -ENOSPC; - - return 0; - } - if (type == DPAA2_QDMA_FD_LONG) { - idx = DPAA2_QDMA_FD_ATT_CNTX(att); - fle_sdd = (void *)(uintptr_t)DPAA2_GET_FD_FLC(fd); + if (type == DPAA2_QDMA_FD_LONG || type == DPAA2_QDMA_FD_SG) { + fle_sdd = (void *)DPAA2_GET_FD_FLC(fd); qdma_vq->fle_elem[*fle_elem_nb] = fle_sdd; (*fle_elem_nb)++; + } + if (type == DPAA2_QDMA_FD_SHORT || + type == DPAA2_QDMA_FD_LONG) { + idx = DPAA2_QDMA_FD_ATT_CNTX(att); + qdma_vq->idxs[0] = idx; ret = qdma_cntx_idx_ring_eq(qdma_vq->ring_cntx_idx, - &idx, 1, free_space); + qdma_vq->idxs, 1, free_space); if (unlikely(ret != 1)) return -ENOSPC; return 0; } if (type == DPAA2_QDMA_FD_SG) { - fle_sdd = (void *)(uintptr_t)DPAA2_GET_FD_FLC(fd); - qdma_vq->fle_elem[*fle_elem_nb] = fle_sdd; - (*fle_elem_nb)++; cntx_sg = container_of(fle_sdd, struct qdma_cntx_sg, fle_sdd); ret = qdma_cntx_idx_ring_eq(qdma_vq->ring_cntx_idx, diff --git a/drivers/dma/dpaa2/dpaa2_qdma.h b/drivers/dma/dpaa2/dpaa2_qdma.h index e2d2eb4fa8..98c64f7b45 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.h +++ b/drivers/dma/dpaa2/dpaa2_qdma.h @@ -290,6 +290,7 @@ struct qdma_virt_queue { struct qdma_cntx_idx_ring *ring_cntx_idx; /**Used for silent enabled*/ + uint16_t idxs[DPAA2_QDMA_MAX_DESC]; struct qdma_cntx_sg *cntx_sg[DPAA2_QDMA_MAX_DESC]; struct qdma_cntx_fle_sdd *cntx_fle_sdd[DPAA2_QDMA_MAX_DESC]; uint16_t silent_idx; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 10/45] bus/fslmc: defer bus initialization to probe 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (8 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 09/45] dma/dpaa2: fix array-bounds warning in dequeue path Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 11/45] dma/dpaa2: validate IOVA in pre-populate helpers Prashant Gupta ` (40 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev The fslmc bus initialization (register the sequence number mbuf dynfield, set up the VFIO group, DMA map the memory segments) needs the DPDK heap and the memory segment list in shared (hugepage) memory for multi-process sharing. But these are not available during the bus scan (EAL runs rte_bus_scan() before memzone, memory and malloc heap init), so it fails there. Device discovery does not need it, and get_iommu_class() only checks sysfs paths to report the IOVA mode, so the init is not needed in scan. Move it back to probe. Fixes: cdefd2e980bd ("drivers/bus: initialize NXP bus specifics in scan") Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- drivers/bus/fslmc/fslmc_bus.c | 92 +++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index 3626b12316..ee162b0ed8 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -368,46 +368,6 @@ rte_fslmc_scan(void) /* If debugging is enabled, device list is dumped to log output */ dump_device_list(); - /* Bus initialization - only if devices were found */ - if (!TAILQ_EMPTY(&rte_fslmc_bus.device_list)) { - static const struct rte_mbuf_dynfield dpaa2_seqn_dynfield_desc = { - .name = DPAA2_SEQN_DYNFIELD_NAME, - .size = sizeof(dpaa2_seqn_t), - .align = alignof(dpaa2_seqn_t), - }; - - dpaa2_seqn_dynfield_offset = - rte_mbuf_dynfield_register(&dpaa2_seqn_dynfield_desc); - if (dpaa2_seqn_dynfield_offset < 0) { - DPAA2_BUS_ERR("Failed to register mbuf field for dpaa sequence number"); - return 0; - } - - ret = fslmc_vfio_setup_group(); - if (ret) { - DPAA2_BUS_ERR("Unable to setup VFIO %d", ret); - return 0; - } - - /* Map existing segments as well as, in case of hotpluggable memory, - * install callback handler. - */ - if (rte_eal_process_type() == RTE_PROC_PRIMARY) { - ret = fslmc_vfio_dmamap(); - if (ret) { - DPAA2_BUS_ERR("Unable to DMA map existing VAs: (%d)", ret); - DPAA2_BUS_ERR("FSLMC VFIO Mapping failed"); - return 0; - } - } - - ret = fslmc_vfio_process_group(); - if (ret) { - DPAA2_BUS_ERR("Unable to setup devices %d", ret); - return 0; - } - } - process_once = 1; return 0; @@ -423,6 +383,56 @@ rte_fslmc_scan(void) return 0; } +/* Bus initialization needs the DPDK heap and DMA mapping of the memory + * segments, which EAL only sets up after the bus scan, so it is done here. + */ +static int +rte_fslmc_probe(struct rte_bus *bus) +{ + static const struct rte_mbuf_dynfield dpaa2_seqn_dynfield_desc = { + .name = DPAA2_SEQN_DYNFIELD_NAME, + .size = sizeof(dpaa2_seqn_t), + .align = alignof(dpaa2_seqn_t), + }; + int ret; + + if (TAILQ_EMPTY(&rte_fslmc_bus.device_list)) + return 0; + + dpaa2_seqn_dynfield_offset = + rte_mbuf_dynfield_register(&dpaa2_seqn_dynfield_desc); + if (dpaa2_seqn_dynfield_offset < 0) { + DPAA2_BUS_ERR("Failed to register mbuf field for dpaa sequence number"); + return 0; + } + + ret = fslmc_vfio_setup_group(); + if (ret) { + DPAA2_BUS_ERR("Unable to setup VFIO %d", ret); + return 0; + } + + /* Map existing segments as well as, in case of hotpluggable memory, + * install callback handler. + */ + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + ret = fslmc_vfio_dmamap(); + if (ret) { + DPAA2_BUS_ERR("Unable to DMA map existing VAs: (%d)", ret); + DPAA2_BUS_ERR("FSLMC VFIO Mapping failed"); + return 0; + } + } + + ret = fslmc_vfio_process_group(); + if (ret) { + DPAA2_BUS_ERR("Unable to setup devices %d", ret); + return 0; + } + + return rte_bus_generic_probe(bus); +} + static bool fslmc_bus_match(const struct rte_driver *drv, const struct rte_device *dev) { @@ -544,7 +554,7 @@ fslmc_bus_unplug_device(struct rte_device *rte_dev) struct rte_bus rte_fslmc_bus = { .scan = rte_fslmc_scan, - .probe = rte_bus_generic_probe, + .probe = rte_fslmc_probe, .cleanup = rte_fslmc_close, .parse = rte_fslmc_parse, .dev_compare = fslmc_dev_compare, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 11/45] dma/dpaa2: validate IOVA in pre-populate helpers 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (9 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 10/45] bus/fslmc: defer bus initialization to probe Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 12/45] dma/dpaa2: optimize context index ring enqueue Prashant Gupta ` (39 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> fle_sdd_pre_populate() and fle_sdd_sg_pre_populate() converted the SDD and SG entry virtual addresses to IOVA with DPAA2_VADDR_TO_IOVA(), which does not verify that the range is actually mapped in the IOMMU/SMMU. An unmapped buffer was silently programmed into the hardware descriptor, leading to an SMMU translation fault at transfer time that is hard to trace back to the missing mapping. Use DPAA2_VADDR_TO_IOVA_AND_CHECK() for the SDD, source SG and destination SG buffers and report the offending address and size when the translation is missing, so the misconfiguration is caught early and clearly. Both helpers now return an error code which is propagated to the caller instead of continuing with an invalid descriptor. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/dma/dpaa2/dpaa2_qdma.c | 50 ++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 45d7a99805..4ad72c5816 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -180,14 +180,23 @@ dpaa2_qdma_multi_eq(struct qdma_virt_queue *qdma_vq) return num_tx; } -static void +static int fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, struct dpaa2_qdma_rbp *rbp, uint64_t src, uint64_t dest, uint32_t fmt) { struct qbman_fle *fle = fle_sdd->fle; struct qdma_sdd *sdd = fle_sdd->sdd; - uint64_t sdd_iova = DPAA2_VADDR_TO_IOVA(sdd); + uint64_t sdd_iova, iova_size; + + iova_size = sizeof(struct qdma_sdd) * DPAA2_QDMA_MAX_SDD; + sdd_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(sdd, iova_size); + if (sdd_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for sdd(%p)(size=%" PRIx64 ")", + sdd, iova_size); + + return -ENOMEM; + } /* first frame list to source descriptor */ DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_SDD_FLE], sdd_iova); @@ -256,6 +265,8 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, /* Final bit: 1, for last frame list */ DPAA2_SET_FLE_FIN(&fle[DPAA2_QDMA_DST_FLE]); + + return 0; } static void @@ -283,22 +294,39 @@ sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) } } -static void +static int fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, struct qdma_virt_queue *qdma_vq) { struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; struct qdma_sg_entry *dst_sge = sg_cntx->sg_dst_entry; - rte_iova_t src_sge_iova, dst_sge_iova; + rte_iova_t src_sge_iova, dst_sge_iova, iova_size; struct dpaa2_qdma_rbp *rbp = &qdma_vq->rbp; memset(sg_cntx, 0, sizeof(struct qdma_cntx_sg)); - src_sge_iova = DPAA2_VADDR_TO_IOVA(src_sge); - dst_sge_iova = DPAA2_VADDR_TO_IOVA(dst_sge); + iova_size = RTE_DPAAX_QDMA_JOB_SUBMIT_MAX * + sizeof(struct qdma_sg_entry); + + src_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(src_sge, iova_size); + if (src_sge_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for src_sge(%p)(size=%" PRIx64 ")", + src_sge, iova_size); + + return -ENOMEM; + } + + dst_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(dst_sge, iova_size); + if (dst_sge_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for dst_sge(%p)(size=%" PRIx64 ")", + dst_sge, iova_size); + + return -ENOMEM; + } sg_entry_pre_populate(sg_cntx); - fle_sdd_pre_populate(&sg_cntx->fle_sdd, + + return fle_sdd_pre_populate(&sg_cntx->fle_sdd, rbp, src_sge_iova, dst_sge_iova, QBMAN_FLE_WORD4_FMT_SGE); } @@ -669,7 +697,9 @@ dpaa2_qdma_copy_sg(void *dev_private, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + if (ret) + return ret; if (!qdma_dev->is_silent && cntx_sg && idx_addr) { for (i = 0; i < nb_src; i++) cntx_sg->cntx_idx[i] = idx_addr[i]; @@ -871,9 +901,11 @@ dpaa2_qdma_long_copy(struct qdma_virt_queue *qdma_vq, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - fle_sdd_pre_populate(fle_sdd, + ret = fle_sdd_pre_populate(fle_sdd, &qdma_vq->rbp, 0, 0, QBMAN_FLE_WORD4_FMT_SBF); + if (ret) + return ret; } fle_post_populate(fle, src, dst, length); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 12/45] dma/dpaa2: optimize context index ring enqueue 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (10 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 11/45] dma/dpaa2: validate IOVA in pre-populate helpers Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 13/45] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta ` (38 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> qdma_cntx_idx_ring_eq() copied the context indices into the ring one element at a time in a loop, updating the tail on every iteration. Replace the per-element loop with rte_memcpy(), handling the ring wrap-around as at most two contiguous copies, and update the tail once. This reduces the per-burst overhead on the dequeue completion path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/dma/dpaa2/dpaa2_qdma.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 4ad72c5816..1e9ec463aa 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -66,15 +66,23 @@ qdma_cntx_idx_ring_eq(struct qdma_cntx_idx_ring *ring, const uint16_t *elem, uint16_t nb, uint16_t *free_space) { - uint16_t i; - if (unlikely(nb > ring->free_space)) return 0; - for (i = 0; i < nb; i++) { - ring->cntx_idx_ring[ring->tail] = elem[i]; - ring->tail = (ring->tail + 1) & - (DPAA2_QDMA_MAX_DESC - 1); + if ((ring->tail + nb) < DPAA2_QDMA_MAX_DESC) { + rte_memcpy(&ring->cntx_idx_ring[ring->tail], + elem, nb * sizeof(uint16_t)); + ring->tail += nb; + } else { + rte_memcpy(&ring->cntx_idx_ring[ring->tail], + elem, + (DPAA2_QDMA_MAX_DESC - ring->tail) * + sizeof(uint16_t)); + rte_memcpy(&ring->cntx_idx_ring[0], + &elem[DPAA2_QDMA_MAX_DESC - ring->tail], + (nb - DPAA2_QDMA_MAX_DESC + ring->tail) * + sizeof(uint16_t)); + ring->tail = (ring->tail + nb) & (DPAA2_QDMA_MAX_DESC - 1); } ring->free_space -= nb; ring->nb_in_ring += nb; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 13/45] drivers: add dpaa2 DMA bypass memory translation option 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (11 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 12/45] dma/dpaa2: optimize context index ring enqueue Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 14/45] mempool/dpaa2: support ops index from primary in secondary Prashant Gupta ` (37 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add RTE_DPAAX_QDMA_BMT_FLAG flag to allow callers to bypass memory translation (BMT) for DMA operations. This is needed for some PCIe scenarios where IOMMU translation should be skipped. The flag is propagated to all SG entry and FD populate helpers via a new 'bmt' parameter, defaulting to DISABLE when the flag is not set. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/common/dpaax/rte_pmd_dpaax_qdma.h | 4 +- drivers/dma/dpaa2/dpaa2_qdma.c | 59 ++++++++++------------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/drivers/common/dpaax/rte_pmd_dpaax_qdma.h b/drivers/common/dpaax/rte_pmd_dpaax_qdma.h index 8f2fc83f8d..6bd72b0b0e 100644 --- a/drivers/common/dpaax/rte_pmd_dpaax_qdma.h +++ b/drivers/common/dpaax/rte_pmd_dpaax_qdma.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2021-2024 NXP + * Copyright 2021-2024, 2026 NXP */ #ifndef RTE_PMD_DPAAX_QDMA_H @@ -7,6 +7,8 @@ #include <rte_compat.h> +#define RTE_DPAAX_QDMA_BMT_FLAG RTE_BIT64(7) + #define RTE_DPAAX_QDMA_COPY_IDX_OFFSET 8 #define RTE_DPAAX_QDMA_SG_IDX_ADDR_ALIGN \ RTE_BIT64(RTE_DPAAX_QDMA_COPY_IDX_OFFSET) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 1e9ec463aa..e73b7dbb1e 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -278,7 +278,7 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, } static void -sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) +sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx, int bmt) { uint16_t i; struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; @@ -288,23 +288,17 @@ sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) /* source SG */ src_sge[i].ctrl.sl = QDMA_SG_SL_LONG; src_sge[i].ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - src_sge[i].ctrl.bmt = QDMA_SG_BMT_DISABLE; + src_sge[i].ctrl.bmt = bmt; /* destination SG */ dst_sge[i].ctrl.sl = QDMA_SG_SL_LONG; dst_sge[i].ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - dst_sge[i].ctrl.bmt = QDMA_SG_BMT_DISABLE; + dst_sge[i].ctrl.bmt = bmt; } } static int fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, - struct qdma_virt_queue *qdma_vq) + struct qdma_virt_queue *qdma_vq, int bmt) { struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; struct qdma_sg_entry *dst_sge = sg_cntx->sg_dst_entry; @@ -332,7 +326,7 @@ fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, return -ENOMEM; } - sg_entry_pre_populate(sg_cntx); + sg_entry_pre_populate(sg_cntx, bmt); return fle_sdd_pre_populate(&sg_cntx->fle_sdd, rbp, src_sge_iova, dst_sge_iova, @@ -398,7 +392,7 @@ sg_fle_post_populate(struct qbman_fle fle[], static inline uint32_t sg_entry_populate(const struct rte_dma_sge *src, const struct rte_dma_sge *dst, struct qdma_cntx_sg *sg_cntx, - uint16_t nb_sge) + uint16_t nb_sge, int bmt) { uint16_t i; uint32_t total_len = 0; @@ -414,19 +408,13 @@ sg_entry_populate(const struct rte_dma_sge *src, src_sge->data_len.data_len_sl0 = src[i].length; src_sge->ctrl.sl = QDMA_SG_SL_LONG; src_sge->ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - src_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE; + src_sge->ctrl.bmt = bmt; dst_sge->addr_lo = (uint32_t)dst[i].addr; dst_sge->addr_hi = (dst[i].addr >> 32); dst_sge->data_len.data_len_sl0 = dst[i].length; dst_sge->ctrl.sl = QDMA_SG_SL_LONG; dst_sge->ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - dst_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE; + dst_sge->ctrl.bmt = bmt; total_len += src[i].length; if (i == (nb_sge - 1)) { @@ -705,7 +693,9 @@ dpaa2_qdma_copy_sg(void *dev_private, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); if (ret) return ret; if (!qdma_dev->is_silent && cntx_sg && idx_addr) { @@ -726,7 +716,9 @@ dpaa2_qdma_copy_sg(void *dev_private, offsetof(struct qdma_cntx_sg, sg_src_entry); dst_sge_iova = cntx_iova + offsetof(struct qdma_cntx_sg, sg_dst_entry); - len = sg_entry_populate(src, dst, cntx_sg, nb_src); + len = sg_entry_populate(src, dst, cntx_sg, nb_src, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); fle_populate(fle, sdd, sdd_iova, &qdma_vq->rbp, src_sge_iova, dst_sge_iova, len, @@ -759,14 +751,14 @@ dpaa2_qdma_copy_sg(void *dev_private, static inline void qdma_populate_fd_pci(uint64_t src, uint64_t dest, uint32_t len, struct qbman_fd *fd, - struct dpaa2_qdma_rbp *rbp, int ser) + struct dpaa2_qdma_rbp *rbp, int ser, int bmt) { fd->simple_pci.saddr_lo = lower_32_bits(src); fd->simple_pci.saddr_hi = upper_32_bits(src); fd->simple_pci.len_sl = len; - fd->simple_pci.bmt = DPAA2_QDMA_BMT_DISABLE; + fd->simple_pci.bmt = bmt; fd->simple_pci.fmt = DPAA2_QDMA_FD_SHORT_FORMAT; fd->simple_pci.sl = 1; fd->simple_pci.ser = ser; @@ -802,14 +794,14 @@ qdma_populate_fd_pci(uint64_t src, uint64_t dest, static inline void qdma_populate_fd_ddr(uint64_t src, uint64_t dest, - uint32_t len, struct qbman_fd *fd, int ser) + uint32_t len, struct qbman_fd *fd, int ser, int bmt) { fd->simple_ddr.saddr_lo = lower_32_bits(src); fd->simple_ddr.saddr_hi = upper_32_bits(src); fd->simple_ddr.len = len; - fd->simple_ddr.bmt = DPAA2_QDMA_BMT_DISABLE; + fd->simple_ddr.bmt = bmt; fd->simple_ddr.fmt = DPAA2_QDMA_FD_SHORT_FORMAT; fd->simple_ddr.sl = 1; fd->simple_ddr.ser = ser; @@ -847,15 +839,16 @@ dpaa2_qdma_short_copy(struct qdma_virt_queue *qdma_vq, if (qdma_vq->rbp.drbp || qdma_vq->rbp.srbp) { /** PCIe EP*/ - qdma_populate_fd_pci(src, - dst, length, - fd, &qdma_vq->rbp, - is_silent ? 0 : 1); + qdma_populate_fd_pci(src, dst, length, + fd, &qdma_vq->rbp, is_silent ? 0 : 1, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } else { /** DDR or PCIe RC*/ - qdma_populate_fd_ddr(src, - dst, length, - fd, is_silent ? 0 : 1); + qdma_populate_fd_ddr(src, dst, length, + fd, is_silent ? 0 : 1, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } dpaa2_qdma_fd_save_att(fd, DPAA2_QDMA_IDX_FROM_FLAG(flags), DPAA2_QDMA_FD_SHORT); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 14/45] mempool/dpaa2: support ops index from primary in secondary 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (12 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 13/45] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 15/45] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (36 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Hemant Agrawal From: Jun Yang <jun.yang@nxp.com> Secondary processes call rte_dpaa2_mpool_get_ops_idx() but the ops index is registered only in the primary process. The secondary had no way to learn the index, causing it to use the initial sentinel value RTE_MEMPOOL_MAX_OPS_IDX and return an error. Register an IPC action handler in the primary during pool creation. Secondary processes send DPAA2_POOL_OPS_IDX_REQ over the dpaa2_pool_mp_sync channel and receive the ops index back. Also handle the case where rte_mp_action_register returns ENOTSUP (e.g. no secondary process support enabled at build time) by treating it as non-fatal, and improve the error message in rte_hw_mbuf_free_pool to include the pool name. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/mempool/dpaa2/dpaa2_hw_mempool.c | 88 +++++++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c index ee001d8ce0..f19b6c039a 100644 --- a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c +++ b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c @@ -34,16 +34,90 @@ #include <dpaax_iova_table.h> +#define DPAA2_POOL_MP_SYNC "dpaa2_pool_mp_sync" +#define DPAA2_POOL_OPS_IDX_REQ 0x100 +#define DPAA2_POOL_OPS_IDX_RSP 0x101 + +static int s_dpaa2_pool_mp_msg_setup; + +struct dpaa2_pool_mp_msg { + uint16_t msg_type; + uint8_t msg_data[]; +}; + RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_bpid_info) struct dpaa2_bp_info *rte_dpaa2_bpid_info; static struct dpaa2_bp_list *h_bp_list; static int16_t s_dpaa2_pool_ops_idx = RTE_MEMPOOL_MAX_OPS_IDX; +static int +dpaa2_mbuf_pool_mp_primary(const struct rte_mp_msg *msg, + const void *peer) +{ + struct rte_mp_msg reply; + const struct dpaa2_pool_mp_msg *req_msg = (const void *)msg->param; + struct dpaa2_pool_mp_msg *rsp_msg = (void *)reply.param; + + memset(&reply, 0, sizeof(reply)); + + switch (req_msg->msg_type) { + case DPAA2_POOL_OPS_IDX_REQ: + rsp_msg->msg_type = DPAA2_POOL_OPS_IDX_RSP; + rte_memcpy(rsp_msg->msg_data, &s_dpaa2_pool_ops_idx, + sizeof(s_dpaa2_pool_ops_idx)); + break; + default: + DPAA2_MEMPOOL_ERR("%s received invalid request(%d)", + __func__, req_msg->msg_type); + return -ENOTSUP; + } + + strlcpy(reply.name, DPAA2_POOL_MP_SYNC, sizeof(reply.name)); + return rte_mp_reply(&reply, peer); +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_mpool_get_ops_idx) int rte_dpaa2_mpool_get_ops_idx(void) { - return s_dpaa2_pool_ops_idx; + struct rte_mp_msg mp_req; + struct rte_mp_reply mp_reply; + struct timespec ts = {.tv_sec = 5, .tv_nsec = 0}; + int ret = 0; + struct dpaa2_pool_mp_msg *req_msg = (void *)mp_req.param; + struct dpaa2_pool_mp_msg *rsp_msg; + + if (rte_eal_process_type() == RTE_PROC_PRIMARY || + s_dpaa2_pool_ops_idx != RTE_MEMPOOL_MAX_OPS_IDX) + return s_dpaa2_pool_ops_idx; + + strlcpy(mp_req.name, DPAA2_POOL_MP_SYNC, sizeof(mp_req.name)); + req_msg->msg_type = DPAA2_POOL_OPS_IDX_REQ; + memset(&mp_reply, 0, sizeof(struct rte_mp_reply)); + ret = rte_mp_request_sync(&mp_req, &mp_reply, &ts); + if (ret) { + DPAA2_MEMPOOL_ERR("%s Failed to get response(%d)", + __func__, ret); + return ret; + } + if (!mp_reply.msgs) { + DPAA2_MEMPOOL_ERR("%s Failed to get response message", + __func__); + return -EINVAL; + } + rsp_msg = (void *)mp_reply.msgs; + if (rsp_msg->msg_type == DPAA2_POOL_OPS_IDX_RSP) { + rte_memcpy(&s_dpaa2_pool_ops_idx, rsp_msg->msg_data, + sizeof(s_dpaa2_pool_ops_idx)); + ret = 0; + } else { + DPAA2_MEMPOOL_ERR("%s received invalid response(%d)", + __func__, rsp_msg->msg_type); + ret = -EINVAL; + } + free(mp_reply.msgs); + + return ret; } static int @@ -128,10 +202,18 @@ rte_hw_mbuf_create_pool(struct rte_mempool *mp) if (s_dpaa2_pool_ops_idx == RTE_MEMPOOL_MAX_OPS_IDX) { s_dpaa2_pool_ops_idx = mp->ops_index; } else if (s_dpaa2_pool_ops_idx != mp->ops_index) { - DPAA2_MEMPOOL_ERR("Only single ops index only"); + DPAA2_MEMPOOL_ERR("Single ops index only"); ret = -EINVAL; goto err4; } + if (rte_eal_process_type() == RTE_PROC_PRIMARY && + !s_dpaa2_pool_mp_msg_setup) { + ret = rte_mp_action_register(DPAA2_POOL_MP_SYNC, + dpaa2_mbuf_pool_mp_primary); + if (ret && rte_errno != ENOTSUP) + return ret; + s_dpaa2_pool_mp_msg_setup = 1; + } bp_list->next = h_bp_list; bp_list->mp = mp; @@ -172,7 +254,7 @@ rte_hw_mbuf_free_pool(struct rte_mempool *mp) struct dpaa2_dpbp_dev *dpbp_node; if (!mp->pool_data) { - DPAA2_MEMPOOL_ERR("Not a valid dpaa2 buffer pool"); + DPAA2_MEMPOOL_ERR("Not a valid dpaa2 buffer pool %s", mp->name); return; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 15/45] net/dpaa2: set Tx confirmation on device init 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (13 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 14/45] mempool/dpaa2: support ops index from primary in secondary Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 16/45] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta ` (35 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f211357919..c95704d4ca 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3624,6 +3599,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 16/45] drivers: optimize dpaa2 Tx queue and channel mapping 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (14 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 15/45] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 17/45] net/dpaa2: support larger burst size Prashant Gupta ` (34 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Allocate TX queues based on dpni attribute and align the bounds check with the RX queue logic: - compute nb_tx_queues from num_tx_tcs * num_queues (respecting DPNI_OPT_SINGLE_SENDER) and cap at MAX_TX_QUEUES (128) - cap nb_rx_queues at MAX_RX_QUEUES (128) - cap num_channels at DPAA2_MAX_CHANNELS - assign tc_index/flow_id at queue-allocation time instead of at queue-setup time - replace the open-coded (channel << 8 | tc) with DPNI_BUILD_PARAM(channel, tc) throughout tx_queue_setup - initialize fqid to DPAA2_INVALID_FQ_ID and use it as the already-configured guard (replacing DPAA2_INVALID_FLOW_ID) - add a per-device tx_channels[] array for channel mapping Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/dpaa2_ethdev.c | 112 ++++++++++++++---------- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +- 3 files changed, 70 insertions(+), 48 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index ef65e7895a..f0bc9a3063 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -82,6 +82,7 @@ #define DPAA2_DPCI_MAX_QUEUES 2 #define DPAA2_INVALID_FLOW_ID 0xffff +#define DPAA2_INVALID_FQ_ID ((uint32_t)(-1)) #define DPAA2_INVALID_CGID 0xff #define SEC_FLC_DHR_OUTBOUND (-114) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c95704d4ca..d79dfa7114 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -519,17 +519,13 @@ static int dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint16_t dist_idx; - uint32_t vq_id; - uint8_t num_rxqueue_per_tc; - struct dpaa2_queue *mc_q, *mcq; + uint8_t num_queue_per_tc; + struct dpaa2_queue *mc_q, *dpaa2_q; uint32_t tot_queues; int i, ret = 0; - struct dpaa2_queue *dpaa2_q; PMD_INIT_FUNC_TRACE(); - num_rxqueue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); if (priv->flags & DPAA2_TX_CONF_ENABLE) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else @@ -541,8 +537,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) return -ENOBUFS; } + num_queue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); for (i = 0; i < priv->nb_rx_queues; i++) { mc_q->eth_data = dev->data; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->rx_vq[i] = mc_q++; dpaa2_q = priv->rx_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -566,9 +566,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } + num_queue_per_tc = (priv->nb_tx_queues / priv->num_tx_tc); for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->flow_id = DPAA2_INVALID_FLOW_ID; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_vq[i] = mc_q++; dpaa2_q = (struct dpaa2_queue *)priv->tx_vq[i]; dpaa2_q->cscn = rte_malloc(NULL, @@ -583,8 +586,9 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->tc_index = i; - mc_q->flow_id = 0; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_conf_vq[i] = mc_q++; dpaa2_q = priv->tx_conf_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -594,14 +598,6 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - vq_id = 0; - for (dist_idx = 0; dist_idx < priv->nb_rx_queues; dist_idx++) { - mcq = priv->rx_vq[vq_id]; - mcq->tc_index = dist_idx / num_rxqueue_per_tc; - mcq->flow_id = dist_idx % num_rxqueue_per_tc; - vq_id++; - } - return 0; fail_tx_conf: i -= 1; @@ -977,6 +973,12 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, return ret; } dpaa2_q = priv->rx_vq[rx_queue_id]; + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", + dev->data->name, rx_queue_id); + dev->data->rx_queues[rx_queue_id] = dpaa2_q; + return 0; + } dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1165,7 +1167,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->offloads = tx_conf->offloads; /* Return if queue already configured */ - if (dpaa2_q->flow_id != DPAA2_INVALID_FLOW_ID) { + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: TXQ[%d] has been setup", + dev->data->name, tx_queue_id); dev->data->tx_queues[tx_queue_id] = dpaa2_q; return 0; } @@ -1173,26 +1177,24 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - tc_id = tx_queue_id % priv->num_tx_tc; - channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; - flow_id = 0; + tc_id = dpaa2_q->tc_index; + flow_id = dpaa2_q->flow_id; + if (tc_id < priv->num_channels) + channel_id = priv->tx_channels[tc_id]; + else + channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); if (ret) { - DPAA2_PMD_ERR("Error in setting the tx flow: " - "tc_id=%d, flow=%d err=%d", - tc_id, flow_id, ret); - return ret; + DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", + ret, dev->data->name, tc_id, flow_id); + return ret; } - dpaa2_q->flow_id = flow_id; - - dpaa2_q->tc_index = tc_id; - ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, ((channel_id << 8) | dpaa2_q->tc_index), - dpaa2_q->flow_id, &tx_flow_cfg, &qid); + DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1231,10 +1233,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_set_congestion_notification(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), &cong_notif_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), &cong_notif_cfg); if (ret) { - DPAA2_PMD_ERR("Set TX congestion notification err=%d", - ret); + DPAA2_PMD_ERR("Set TX congestion notification err=%d", ret); return ret; } } @@ -1242,31 +1243,32 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dev->data->tx_queues[tx_queue_id] = dpaa2_q; if (priv->flags & DPAA2_TX_CONF_ENABLE) { + tc_id = dpaa2_tx_conf_q->tc_index; + flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; options = options | DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, - options, &tx_conf_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, options, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", - dpaa2_tx_conf_q->tc_index, - dpaa2_tx_conf_q->flow_id, ret); + tc_id, flow_id, ret); return ret; } ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, &tx_conf_cfg, &qid); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_conf_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; } dpaa2_tx_conf_q->fqid = qid.fqid; } + return 0; } @@ -3553,10 +3555,28 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; - for (i = 0; i < attr.num_rx_tcs; i++) - priv->nb_rx_queues += attr.num_queues; - - priv->nb_tx_queues = attr.num_tx_tcs * attr.num_channels; + priv->nb_rx_queues = attr.num_rx_tcs * attr.num_queues; + if (priv->nb_rx_queues > MAX_RX_QUEUES) { + DPAA2_PMD_WARN("Too many RXQs(%d) > %d, reduce it to %d", + priv->nb_rx_queues, MAX_RX_QUEUES, MAX_RX_QUEUES); + priv->nb_rx_queues = MAX_RX_QUEUES; + } + if (attr.options & DPNI_OPT_SINGLE_SENDER) + priv->nb_tx_queues = attr.num_tx_tcs * 1; + else + priv->nb_tx_queues = attr.num_tx_tcs * attr.num_queues; + if (priv->nb_tx_queues > MAX_TX_QUEUES) { + DPAA2_PMD_WARN("Too many TXQs(%d) > %d, reduce it to %d", + priv->nb_tx_queues, MAX_TX_QUEUES, MAX_TX_QUEUES); + priv->nb_tx_queues = MAX_TX_QUEUES; + } + if (priv->num_channels > DPAA2_MAX_CHANNELS) { + DPAA2_PMD_WARN("Too many TX channels(%d) > %d, reduce it to %d", + priv->num_channels, DPAA2_MAX_CHANNELS, DPAA2_MAX_CHANNELS); + priv->num_channels = DPAA2_MAX_CHANNELS; + } + for (i = 0; i < priv->num_channels; i++) + priv->tx_channels[i] = i; DPAA2_PMD_DEBUG("RX-TC= %d, rx_queues= %d, tx_queues=%d, max_cgs=%d", priv->num_rx_tc, priv->nb_rx_queues, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..0366315ec7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -28,7 +28,7 @@ #define MAX_TCS DPNI_MAX_TC #define MAX_RX_QUEUES 128 -#define MAX_TX_QUEUES 16 +#define MAX_TX_QUEUES 128 #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 @@ -390,13 +390,14 @@ struct dpaa2_dev_priv { int32_t hw_id; int32_t qdid; uint16_t token; + uint16_t tx_channels[DPAA2_MAX_CHANNELS]; uint8_t nb_tx_queues; uint8_t nb_rx_queues; uint32_t options; void *rx_vq[MAX_RX_QUEUES]; void *tx_vq[MAX_TX_QUEUES]; struct dpaa2_bp_list *bp_list; /**<Attached buffer pool list */ - void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; + void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ uint8_t max_mac_filters; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 17/45] net/dpaa2: support larger burst size 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (15 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 16/45] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 18/45] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (33 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..0e1b2c5b54 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (priv->dpni_ver_major == 8 && priv->dpni_ver_minor >= 7) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : (64 * 1024); + + return (64 * 1024); +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 18/45] net/dpaa2: support MPLS and PPPoE flow distribution 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (16 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 17/45] net/dpaa2: support larger burst size Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 19/45] net/dpaa2: support meter and policing Prashant Gupta ` (32 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..90e0b66258 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 19/45] net/dpaa2: support meter and policing 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (17 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 18/45] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 20/45] net/dpaa2: support flow drop action Prashant Gupta ` (31 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API to the dpaa2 PMD. The implementation registers the rte_mtr operations through the ".mtr_ops_get" dev_ops hook and maintains software bookkeeping of meter profiles, policies and meter objects under a per-device spinlock. Supported algorithms are trTCM RFC 2698 and trTCM RFC 4115 in both byte and packet modes. Meter policies support drop and pass-through actions on the red color. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 1 + drivers/net/dpaa2/dpaa2_ethdev.h | 29 ++ drivers/net/dpaa2/dpaa2_meter.c | 588 +++++++++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 23 +- drivers/net/dpaa2/meson.build | 1 + 5 files changed, 638 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index d79dfa7114..c8abab830f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3322,6 +3322,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 0366315ec7..c5aac65c28 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + int red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -412,6 +436,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -457,6 +482,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -549,6 +577,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..aae88a4d4b --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,588 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = true, + .color_aware_trtcm_rfc4115_supported = true, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /** Align with DPNI policy.*/ + if (!profile->packet_mode) { + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + } else if (profile->packet_mode > DPNI_POLICER_UNIT_FRAMES) { + dpaa2_profile->policer_unit = + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS; + } else { + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + } + + dpaa2_profile->profile_id = profile_id; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter, *tmp; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + DPAA2_PMD_INFO("Meter(id=%d) with profile(%d) is removed!", + meter->meter_id, profile_id); + tmp = meter; + meter = LIST_NEXT(meter, next); + LIST_REMOVE(tmp, next); + rte_free(tmp); + } else { + meter = LIST_NEXT(meter, next); + } + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter, *tmp; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + DPAA2_PMD_INFO("Meter(id=%d) with policy(%d) is removed!", + meter->meter_id, policy_id); + tmp = meter; + meter = LIST_NEXT(meter, next); + LIST_REMOVE(tmp, next); + rte_free(tmp); + } else { + meter = LIST_NEXT(meter, next); + } + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + rte_spinlock_init(&priv->meter_lock); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..d227025e01 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ +#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004 + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1132,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1183,18 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); +int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 20/45] net/dpaa2: support flow drop action 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (18 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 19/45] net/dpaa2: support meter and policing Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 21/45] net/dpaa2: set default flow miss action per device Prashant Gupta ` (30 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 90e0b66258..b2f1778de3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 21/45] net/dpaa2: set default flow miss action per device 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (19 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 20/45] net/dpaa2: support flow drop action Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 22/45] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (29 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global configured only via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable and defaulted to 0. Replace it with a per-device default_flow computed at probe time as the lowest priority flow of the FS table, so that unmatched frames are directed there without depending on an environment variable. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c8abab830f..387a153036 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3545,6 +3545,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MIN(priv->fs_entries, + priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c5aac65c28..4501bd9e49 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -437,6 +437,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b2f1778de3..2e844121a8 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 22/45] net/dpaa2: identify Rx mbuf hash information by FLC 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (20 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 21/45] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 23/45] net/dpaa2: add minimum key size support Prashant Gupta ` (28 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC for mbuf Rx scheduling. An Rx mbuf received from the FS table is marked with RTE_MBUF_F_RX_FDIR along with the TC and flow ID decoded from the FLC low word. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 4501bd9e49..c693989998 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e844121a8..45660df31a 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..7ba6a4563f 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, 0); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 23/45] net/dpaa2: add minimum key size support 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (21 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 22/45] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 24/45] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (27 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 45660df31a..2662c358e4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4532,8 +4535,7 @@ dpaa2_flow_entry_size(uint16_t key_max_size) if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 24/45] net/dpaa2: restructure dpaa2 parser processing 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (22 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 23/45] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 25/45] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (26 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move the parse-result decoding into a dedicated header so that the hardware parser fields are described in one place and shared between the flow code and the Rx path. No functional change is intended. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 172 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1539 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 332 ++--- 5 files changed, 1906 insertions(+), 578 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c693989998..2f552f3e29 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,17 +207,33 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; -extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ @@ -258,42 +308,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -436,6 +450,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -475,6 +490,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -483,6 +501,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -514,6 +533,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..f180955b15 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1539 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_L4_NONFRAG; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type &= ~RTE_PTYPE_L4_NONFRAG; + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 7ba6a4563f..47c8cacdc4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,19 +26,43 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" +#include "dpaa2_parser_decode.h" -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} -static inline rte_mbuf_timestamp_t * -dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) { - return RTE_MBUF_DYNFIELD(mbuf, - dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; } #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ @@ -51,95 +75,108 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) + +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, DPAA2_GET_FD_DROPP(fd)); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + RTE_SET_USED(priv); m->packet_type = RTE_PTYPE_UNKNOWN; + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); - } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - m->ol_flags |= RTE_MBUF_F_RX_FDIR; - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - rte_mbuf_sched_set(m, flow, tc, 0); - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + m->packet_type = dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; } - if (dpaa2_enable_ts[m->port]) { - *dpaa2_timestamp_dynfield(m) = annotation->word2; - m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + *(rte_be64_t *)&word5 = rte_cpu_to_be_64(annotation->word5); + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -249,36 +286,18 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + annotation->word4); - if (dpaa2_enable_ts[mbuf->port]) { - *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; - mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(mbuf)); - } + RTE_SET_USED(priv); /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -307,8 +326,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -336,12 +354,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -381,13 +401,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -397,7 +426,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -413,9 +442,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -674,6 +704,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -729,15 +760,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -792,18 +824,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -909,18 +935,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -989,7 +1014,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1014,7 +1042,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1041,7 +1072,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1151,12 +1185,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1164,6 +1201,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1314,7 +1352,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1336,7 +1374,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1617,8 +1655,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 25/45] net/dpaa2: parse tunnel and fragmented packet types 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (23 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 24/45] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 26/45] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (25 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend the Rx parser to identify additional packet types decoded from the hardware parser summary: IPv4/IPv6 fragments, IPsec ESP, and GTP-U / GTP-C tunnels. The corresponding DPAA2_PKT_TYPE_* values are added and mapped to the matching RTE_PTYPE_* flags in the slow-path parser. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 2f552f3e29..6c72b9012c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 47c8cacdc4..26c84e7125 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -153,6 +153,38 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPC; + break; case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 26/45] net/dpaa2: remove unused soft parser driver 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (24 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 25/45] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 27/45] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta ` (24 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Softparser only supports to be loaded before Linux starts. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 28 ----- drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 -------------------- drivers/net/dpaa2/dpaa2_sparser.h | 202 ------------------------------ drivers/net/dpaa2/meson.build | 1 - 5 files changed, 369 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 387a153036..1df84e1316 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3738,33 +3737,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 80c20272ce..ed038c204b 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 27/45] drivers: refresh dpaa2 MC and SoC version info 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (25 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 26/45] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 28/45] drivers: identify dpaa2 soft parser protocol Prashant Gupta ` (23 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Fix MC revision typo to correct major to minor. Get MC/SoC rev info only once and save them in bus info as well as other information to reduce replicated variables. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 11 +- drivers/bus/fslmc/fslmc_bus.c | 2 + drivers/bus/fslmc/fslmc_vfio.c | 200 ++++++++++++++++++----- drivers/bus/fslmc/fslmc_vfio.h | 30 +++- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 79 +-------- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 7 - drivers/bus/fslmc/private.h | 3 + drivers/net/dpaa2/dpaa2_ethdev.c | 18 +- drivers/net/dpaa2/dpaa2_ethdev.h | 1 + drivers/net/dpaa2/dpaa2_rxtx.c | 10 +- 10 files changed, 225 insertions(+), 136 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index c64ef094d0..b4a5a86318 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2021-2023 NXP + * Copyright 2016,2021-2026 NXP * */ @@ -89,6 +89,14 @@ enum rte_dpaa2_dev_type { DPAA2_DEVTYPE_MAX, }; +struct rte_fslmc_bus_info { + void *mem_pool; + int sp_protocol; + uint64_t mc_rev; + uint32_t svr; + uint32_t pvr; +}; + /** * A structure describing a DPAA2 device. */ @@ -103,6 +111,7 @@ struct rte_dpaa2_device { struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ struct rte_dma_dev *dmadev; /**< DMA device */ + const struct rte_fslmc_bus_info *bus_info; }; typedef int (*rte_dpaa2_obj_create_t)(int vdev_fd, diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index ee162b0ed8..2427421075 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -29,6 +29,7 @@ struct rte_bus rte_fslmc_bus; static int fslmc_bus_device_count[DPAA2_DEVTYPE_MAX]; +struct rte_fslmc_bus_info fslmc_bus_info; #define DPAA2_SEQN_DYNFIELD_NAME "dpaa2_seqn_dynfield" RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) @@ -199,6 +200,7 @@ scan_one_fslmc_device(char *dev_name) goto cleanup; } dev->device.devargs = rte_bus_find_devargs(&rte_fslmc_bus, dev_name); + dev->bus_info = &fslmc_bus_info; /* Update the device found into the device_count table */ fslmc_bus_device_count[dev->dev_type]++; diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index 412b70e5ae..4eb8552696 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -87,6 +87,83 @@ enum { FSLMC_VFIO_SOCKET_REQ_MEM }; +/* Variable to store DPAA2 platform type */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) +uint32_t dpaa2_svr_family; + +/* Variable to store DPAA2 DQRR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) +uint32_t dpaa2_dqrr_size; +/* Variable to store DPAA2 EQCR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) +uint32_t dpaa2_eqcr_size; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_base) +uint32_t dpaa2_cluster_base; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_size) +uint32_t dpaa2_cluster_size; + +struct fslmc_soc_type { + uint32_t svr; + uint32_t cluster_base; + uint32_t cluster_size; + uint32_t qm_dq_size; + uint32_t qm_eq_size; +}; + +/* For LS208X platform There are four clusters with following mapping: + * Cluster 1 (ID = x04) : CPU0, CPU1; + * Cluster 2 (ID = x05) : CPU2, CPU3; + * Cluster 3 (ID = x06) : CPU4, CPU5; + * Cluster 4 (ID = x07) : CPU6, CPU7; + */ +/* For LS108X platform There are two clusters with following mapping: + * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; + * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; + */ +/* For LX2160 platform There are four clusters with following mapping: + * Cluster 1 (ID = x00) : CPU0, CPU1; + * Cluster 2 (ID = x01) : CPU2, CPU3; + * Cluster 3 (ID = x02) : CPU4, CPU5; + * Cluster 4 (ID = x03) : CPU6, CPU7; + * Cluster 1 (ID = x04) : CPU8, CPU9; + * Cluster 2 (ID = x05) : CPU10, CP11; + * Cluster 3 (ID = x06) : CPU12, CPU13; + * Cluster 4 (ID = x07) : CPU14, CPU15; + */ + +int +fslmc_vfio_core_cluster_sdest(uint32_t cpu_id) +{ + int x = cpu_id / dpaa2_cluster_size; + + if (!dpaa2_cluster_size) { + DPAA2_BUS_ERR("SoC type has not been initialized!"); + + return -ENODEV; + } + + return dpaa2_cluster_base + x; +} + +static const struct fslmc_soc_type s_soc_type[] = { + { + SVR_LS2080A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS2088A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS1080A, 2, 4, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LX2160A, 0, 2, + DPAA2_LX2_DQRR_RING_SIZE, DPAA2_LX2_EQCR_RING_SIZE + } +}; + RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_get_mcp_ptr) void * dpaa2_get_mcp_ptr(int portal_idx) @@ -168,6 +245,70 @@ rte_fslmc_object_register(struct rte_dpaa2_object *object) TAILQ_INSERT_TAIL(&dpaa2_obj_list, object, next); } +static int +fslmc_vfio_get_bus_info(void *regs, struct rte_fslmc_bus_info *bus_info) +{ + struct fsl_mc_io mc_io; + struct mc_version mc_ver_info = {0}; + struct mc_soc_version mc_plat_info; + int ret; + size_t i; + + mc_io.regs = regs; + + ret = mc_get_version(&mc_io, CMD_PRI_LOW, &mc_ver_info); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to obtain MC version.", ret); + return ret; + } + DPAA2_BUS_INFO("MC version is %d.%d.%d.", mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + bus_info->mc_rev = RTE_FSL_MC_REV(mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + if (bus_info->mc_rev < RTE_FSL_MC_REV(MC_VER_MAJOR, MC_VER_MINOR, 0)) { + DPAA2_BUS_ERR("DPAA2 MC version not compatible! %d.%d.%d < %d.%d.0", + mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, + MC_VER_MAJOR, MC_VER_MINOR); + return -EPERM; + } + + memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); + ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); + if (ret) { + DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); + return ret; + } + + memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); + ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); + if (ret) { + DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); + return ret; + } + + for (i = 0; i < RTE_DIM(s_soc_type); i++) { + if ((mc_plat_info.svr & DPAA2_SVR_MASK) == s_soc_type[i].svr) { + dpaa2_svr_family = s_soc_type[i].svr; + dpaa2_cluster_base = s_soc_type[i].cluster_base; + dpaa2_cluster_size = s_soc_type[i].cluster_size; + dpaa2_dqrr_size = s_soc_type[i].qm_dq_size; + dpaa2_eqcr_size = s_soc_type[i].qm_eq_size; + break; + } + } + if (i == RTE_DIM(s_soc_type)) { + DPAA2_BUS_ERR("Invalid SoC version: 0x%08x", mc_plat_info.svr); + return -ENODEV; + } + + bus_info->svr = mc_plat_info.svr; + bus_info->pvr = mc_plat_info.pvr; + + return 0; +} + static const char * fslmc_vfio_get_group_name(void) { @@ -1247,9 +1388,9 @@ fslmc_vfio_setup_device(const char *dev_addr, dev_addr); } -static intptr_t vfio_map_mcp_obj(const char *mcp_obj) +static void *fslmc_vfio_map_mcp_obj(const char *mcp_obj) { - intptr_t v_addr = (intptr_t)MAP_FAILED; + void *v_addr = MAP_FAILED; int32_t ret, mc_fd; struct vfio_group_status status = { .argsz = sizeof(status) }; @@ -1265,7 +1406,7 @@ static intptr_t vfio_map_mcp_obj(const char *mcp_obj) goto MC_FAILURE; } - v_addr = (size_t)mmap(NULL, reg_info.size, + v_addr = mmap(NULL, reg_info.size, PROT_WRITE | PROT_READ, MAP_SHARED, mc_fd, reg_info.offset); @@ -1388,7 +1529,7 @@ rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, } static void -fslmc_close_iodevices(struct rte_dpaa2_device *dev, +fslmc_vfio_close_iodevices(struct rte_dpaa2_device *dev, int vfio_fd) { struct rte_dpaa2_object *object = NULL; @@ -1431,11 +1572,11 @@ fslmc_close_iodevices(struct rte_dpaa2_device *dev, } /* - * fslmc_process_iodevices for processing only IO (ETH, CRYPTO, and possibly + * fslmc_vfio_process_iodevices for processing only IO (ETH, CRYPTO, and possibly * EVENT) devices. */ static int -fslmc_process_iodevices(struct rte_dpaa2_device *dev) +fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev) { int dev_fd, ret; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; @@ -1477,12 +1618,10 @@ fslmc_process_iodevices(struct rte_dpaa2_device *dev) } static int -fslmc_process_mcp(struct rte_dpaa2_device *dev) +fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev) { int ret; - intptr_t v_addr; - struct fsl_mc_io dpmng = {0}; - struct mc_version mc_ver_info = {0}; + void *v_addr; rte_mcp_ptr_list = malloc(sizeof(void *) * (MC_PORTAL_INDEX + 1)); if (!rte_mcp_ptr_list) { @@ -1491,15 +1630,16 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) goto cleanup; } - v_addr = vfio_map_mcp_obj(dev->device.name); - if (v_addr == (intptr_t)MAP_FAILED) { + v_addr = fslmc_vfio_map_mcp_obj(dev->device.name); + if (v_addr == MAP_FAILED) { DPAA2_BUS_ERR("Error mapping region (errno = %d)", errno); ret = -1; goto cleanup; } - /* check the MC version compatibility */ - dpmng.regs = (void *)v_addr; + ret = fslmc_vfio_get_bus_info(v_addr, &fslmc_bus_info); + if (ret) + goto cleanup; /* In case of secondary processes, MC version check is no longer * required. @@ -1509,23 +1649,7 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) return 0; } - if (mc_get_version(&dpmng, CMD_PRI_LOW, &mc_ver_info)) { - DPAA2_BUS_ERR("Unable to obtain MC version"); - ret = -1; - goto cleanup; - } - - if ((mc_ver_info.major != MC_VER_MAJOR) || - (mc_ver_info.minor < MC_VER_MINOR)) { - DPAA2_BUS_ERR("DPAA2 MC version not compatible!" - " Expected %d.%d.x, Detected %d.%d.%d", - MC_VER_MAJOR, MC_VER_MINOR, - mc_ver_info.major, mc_ver_info.minor, - mc_ver_info.revision); - ret = -1; - goto cleanup; - } - rte_mcp_ptr_list[MC_PORTAL_INDEX] = (void *)v_addr; + rte_mcp_ptr_list[MC_PORTAL_INDEX] = v_addr; return 0; @@ -1567,7 +1691,7 @@ fslmc_vfio_close_group(void) case DPAA2_CRYPTO: case DPAA2_QDMA: case DPAA2_IO: - fslmc_close_iodevices(dev, vfio_group_fd); + fslmc_vfio_close_iodevices(dev, vfio_group_fd); break; case DPAA2_CON: case DPAA2_CI: @@ -1576,7 +1700,7 @@ fslmc_vfio_close_group(void) if (rte_eal_process_type() == RTE_PROC_SECONDARY) continue; - fslmc_close_iodevices(dev, vfio_group_fd); + fslmc_vfio_close_iodevices(dev, vfio_group_fd); break; case DPAA2_DPRTC: default: @@ -1639,7 +1763,7 @@ fslmc_vfio_process_group(void) } if (!found_mportal) { - ret = fslmc_process_mcp(dev); + ret = fslmc_vfio_process_mcp(dev); if (ret) { DPAA2_BUS_ERR("Unable to map MC Portal"); return ret; @@ -1668,7 +1792,7 @@ fslmc_vfio_process_group(void) current_device = 0; RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { if (dev->dev_type == DPAA2_DPRC) { - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_ERR("Unable to process dprc"); return ret; @@ -1700,7 +1824,7 @@ fslmc_vfio_process_group(void) case DPAA2_ETH: case DPAA2_CRYPTO: case DPAA2_QDMA: - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); @@ -1723,7 +1847,7 @@ fslmc_vfio_process_group(void) /* Call the object creation routine and remove the * device entry from device list */ - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); @@ -1747,7 +1871,7 @@ fslmc_vfio_process_group(void) } } - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h index c995fd67b8..554123ffa6 100644 --- a/drivers/bus/fslmc/fslmc_vfio.h +++ b/drivers/bus/fslmc/fslmc_vfio.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019-2023 NXP + * Copyright 2016,2019-2026 NXP * */ @@ -9,6 +9,8 @@ #define _FSLMC_VFIO_H_ #include <rte_compat.h> +#include <rte_vfio.h> +#include <rte_interrupts.h> /* Pathname of FSL-MC devices directory. */ #define SYSFS_FSL_MC_DEVICES "/sys/bus/fsl-mc/devices" @@ -44,6 +46,30 @@ struct fslmc_vfio_container { extern char *fslmc_container; +extern uint32_t dpaa2_svr_family; +extern uint32_t dpaa2_dqrr_size; +extern uint32_t dpaa2_eqcr_size; +extern uint32_t dpaa2_cluster_base; +extern uint32_t dpaa2_cluster_size; + +#define DPAA2_SVR_MASK 0xffff0000 + +#define SVR_LS1080A 0x87030000 +#define SVR_LS2080A 0x87010000 +#define SVR_LS2088A 0x87090000 +#define SVR_LX2160A 0x87360000 + +#define MC_MAJOR_OFFSET 32 +#define MC_MINOR_OFFSET 16 +#define MC_MINOR_MASK ((((uint64_t)1) << (MC_MAJOR_OFFSET - MC_MINOR_OFFSET)) - 1) +#define MC_REVISION_MASK ((((uint64_t)1) << MC_MINOR_OFFSET) - 1) +#define RTE_FSL_MC_REV(major, minor, revision) \ + ((((uint64_t)(major)) << MC_MAJOR_OFFSET) + \ + (((uint64_t)(minor)) << MC_MINOR_OFFSET) + (revision)) +#define RTE_FSL_MC_REV_MAJOR(rev) ((uint32_t)((rev) >> MC_MAJOR_OFFSET)) +#define RTE_FSL_MC_REV_MINOR(rev) ((uint32_t)(((rev) >> MC_MINOR_OFFSET) & MC_MINOR_MASK)) +#define RTE_FSL_MC_REV_REVISION(rev) ((uint32_t)((rev) & MC_REVISION_MASK)) + __rte_internal int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index); @@ -60,4 +86,6 @@ int fslmc_vfio_close_group(void); char *fslmc_get_container(void); int fslmc_get_container_group(const char *group_name, int *gropuid); int fslmc_vfio_dmamap(void); +int fslmc_vfio_core_cluster_sdest(uint32_t cpu_id); + #endif /* _FSLMC_VFIO_H_ */ diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index e17050b625..20d1bb2a66 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2022 NXP + * Copyright 2016-2026 NXP * */ #include <uapi/linux/vfio.h> @@ -63,45 +63,9 @@ static struct dpio_dev_list dpio_dev_list = TAILQ_HEAD_INITIALIZER(dpio_dev_list); /*!< DPIO device list */ static uint32_t io_space_count; -/* Variable to store DPAA2 platform type */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) -uint32_t dpaa2_svr_family; - -/* Variable to store DPAA2 DQRR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) -uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) -uint8_t dpaa2_eqcr_size; - /* Variable to hold the portal_key, once created.*/ static pthread_key_t dpaa2_portal_key; -/*Stashing Macros default for LS208x*/ -static int dpaa2_core_cluster_base = 0x04; -static int dpaa2_cluster_sz = 2; - -/* For LS208X platform There are four clusters with following mapping: - * Cluster 1 (ID = x04) : CPU0, CPU1; - * Cluster 2 (ID = x05) : CPU2, CPU3; - * Cluster 3 (ID = x06) : CPU4, CPU5; - * Cluster 4 (ID = x07) : CPU6, CPU7; - */ -/* For LS108X platform There are two clusters with following mapping: - * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; - * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; - */ -/* For LX2160 platform There are four clusters with following mapping: - * Cluster 1 (ID = x00) : CPU0, CPU1; - * Cluster 2 (ID = x01) : CPU2, CPU3; - * Cluster 3 (ID = x02) : CPU4, CPU5; - * Cluster 4 (ID = x03) : CPU6, CPU7; - * Cluster 1 (ID = x04) : CPU8, CPU9; - * Cluster 2 (ID = x05) : CPU10, CP11; - * Cluster 3 (ID = x06) : CPU12, CPU13; - * Cluster 4 (ID = x07) : CPU14, CPU15; - */ - static struct dpaa2_dpio_dev *get_dpio_dev_from_id(int32_t dpio_id) { struct dpaa2_dpio_dev *dpio_dev = NULL; @@ -141,14 +105,6 @@ dpaa2_get_core_id(void) return cpu_id; } -static int -dpaa2_core_cluster_sdest(int cpu_id) -{ - int x = cpu_id / dpaa2_cluster_sz; - - return dpaa2_core_cluster_base + x; -} - static void dpaa2_affine_dpio_intr_to_respective_core(int32_t dpio_id, int cpu_id) { @@ -307,15 +263,17 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx /* Set the STASH Destination depending on Current CPU ID. * Valid values of SDEST are 4,5,6,7. Where, */ - sdest = dpaa2_core_cluster_sdest(cpu_id); + sdest = fslmc_vfio_core_cluster_sdest(cpu_id); DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", dpio_dev->index, cpu_id, sdest); + if (sdest < 0) + return sdest; ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token, sdest); if (ret) { DPAA2_BUS_ERR("%d ERROR in SDEST", ret); - return -1; + return ret; } #ifdef RTE_EVENT_DPAA2 @@ -542,33 +500,6 @@ dpaa2_create_dpio_device(int vdev_fd, goto err; } - /* find the SoC type for the first time */ - if (!dpaa2_svr_family) { - struct mc_soc_version mc_plat_info = {0}; - - if (mc_get_soc_version(dpio_dev->dpio, - CMD_PRI_LOW, &mc_plat_info)) { - DPAA2_BUS_ERR("Unable to get SoC version information"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LS1080A) { - dpaa2_core_cluster_base = 0x02; - dpaa2_cluster_sz = 4; - DPAA2_BUS_DEBUG("LS108x (A53) Platform Detected"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LX2160A) { - dpaa2_core_cluster_base = 0x00; - dpaa2_cluster_sz = 2; - DPAA2_BUS_DEBUG("LX2160 Platform Detected"); - } - dpaa2_svr_family = (mc_plat_info.svr & 0xffff0000); - - if (dpaa2_svr_family == SVR_LX2160A) { - dpaa2_dqrr_size = DPAA2_LX2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_LX2_EQCR_RING_SIZE; - } else { - dpaa2_dqrr_size = DPAA2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_EQCR_RING_SIZE; - } - } - if (dpaa2_svr_family == SVR_LX2160A) reg_info.index = DPAA2_SWP_CENA_MEM_REGION; else diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 7e2271cc35..2c559e5354 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -35,13 +35,6 @@ RTE_DECLARE_PER_LCORE(struct dpaa2_io_portal_t, _dpaa2_io); #define DPAA2_PER_LCORE_DQRR_MBUF(i) \ RTE_PER_LCORE(_dpaa2_io).dpio_dev->dpaa2_held_bufs.mbuf[i] -/* Variable to store DPAA2 DQRR size */ -extern uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -extern uint8_t dpaa2_eqcr_size; - -extern struct dpaa2_io_portal_t dpaa2_io_portal[RTE_MAX_LCORE]; - /* Affine a DPIO portal to current processing thread */ __rte_internal int dpaa2_affine_qbman_swp(void); diff --git a/drivers/bus/fslmc/private.h b/drivers/bus/fslmc/private.h index 20a454c3fc..1c8a3e59e9 100644 --- a/drivers/bus/fslmc/private.h +++ b/drivers/bus/fslmc/private.h @@ -11,4 +11,7 @@ extern struct rte_bus rte_fslmc_bus; +/* MC/SoC version and capability info, shared by the bus and VFIO code. */ +extern struct rte_fslmc_bus_info fslmc_bus_info; + #endif /* BUS_FSLMC_PRIVATE_H */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 1df84e1316..e6ce29b2ea 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -329,24 +329,21 @@ dpaa2_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size) { int ret; + uint32_t major, minor, rev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = dev->process_private; struct mc_soc_version mc_plat_info = {0}; - struct mc_version mc_ver_info = {0}; PMD_INIT_FUNC_TRACE(); + major = RTE_FSL_MC_REV_MAJOR(priv->mc_rev); + minor = RTE_FSL_MC_REV_MINOR(priv->mc_rev); + rev = RTE_FSL_MC_REV_REVISION(priv->mc_rev); if (mc_get_soc_version(dpni, CMD_PRI_LOW, &mc_plat_info)) DPAA2_PMD_WARN("\tmc_get_soc_version failed"); - if (mc_get_version(dpni, CMD_PRI_LOW, &mc_ver_info)) - DPAA2_PMD_WARN("\tmc_get_version failed"); - - ret = snprintf(fw_version, fw_size, - "%x-%d.%d.%d", - mc_plat_info.svr, - mc_ver_info.major, - mc_ver_info.minor, - mc_ver_info.revision); + ret = snprintf(fw_version, fw_size, "%x-%d.%d.%d", + mc_plat_info.svr, major, minor, rev); if (ret < 0) return -EINVAL; @@ -3537,6 +3534,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + priv->mc_rev = dpaa2_dev->bus_info->mc_rev; priv->num_rx_tc = attr.num_rx_tcs; priv->num_tx_tc = attr.num_tx_tcs; priv->qos_entries = attr.qos_entries; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 6c72b9012c..f1d1967cd1 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -528,6 +528,7 @@ struct dpaa2_dev_priv { uint32_t *cnt_idx_dma_mem; uint64_t *cnt_values_dma_mem; uint64_t cnt_idx_iova, cnt_values_iova; + uint64_t mc_rev; struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 26c84e7125..f417edf52b 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1123,9 +1123,9 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, /* Function receive frames for a given device and VQ */ struct dpaa2_queue *dpaa2_q = queue; struct qbman_result *dq_storage; - uint32_t fqid = dpaa2_q->fqid; - int ret, num_rx = 0, next_pull = nb_pkts, num_pulled; - uint8_t pending, status; + uint32_t fqid = dpaa2_q->fqid, next_pull = nb_pkts; + int ret; + uint8_t pending, status, num_rx = 0, num_pulled; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; @@ -1269,8 +1269,8 @@ uint16_t dpaa2_dev_tx_conf(void *queue) struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; struct qbman_result *dq_storage; uint32_t fqid = dpaa2_q->fqid; - int ret, num_tx_conf = 0, num_pulled; - uint8_t pending, status; + int ret, num_tx_conf = 0; + uint8_t pending, status, num_pulled; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 28/45] drivers: identify dpaa2 soft parser protocol 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (26 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 27/45] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 29/45] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta ` (22 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Identify if soft parser protocol firmware is loaded by checking firmware magic number. Enable flow/parser of ECPRI, GENEVE, ROCEv2 and VXLAN's spec only with soft parser protocol firmware being loaded. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/fslmc_bus.c | 91 +++++++++++++++++++++- drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_flow.c | 129 ++++++++----------------------- drivers/net/dpaa2/dpaa2_rxtx.c | 10 +++ 4 files changed, 134 insertions(+), 98 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index 2427421075..c3415bc541 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2018-2021 NXP + * Copyright 2016,2018-2026 NXP * */ @@ -8,6 +8,7 @@ #include <dirent.h> #include <stdalign.h> #include <stdbool.h> +#include <sys/mman.h> #include <eal_export.h> #include <rte_log.h> @@ -35,6 +36,93 @@ struct rte_fslmc_bus_info fslmc_bus_info; RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) int dpaa2_seqn_dynfield_offset = -1; +/** For LX2160A, LS2088A and LS1088A*/ +#define WRIOP_CCSR_BASE 0x8b80000 +#define WRIOP_CCSR_CTLU_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 + +#define WRIOP_INGRESS_PARSER_PHY \ + (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) + +struct __rte_packed_begin dpaa2_parser_ccsr { + uint32_t psr_cfg; + uint32_t psr_idle; + uint32_t psr_pclm; + uint8_t psr_ver_min; + uint8_t psr_ver_maj; + uint8_t psr_id1_l; + uint8_t psr_id1_h; + uint32_t psr_rev2; + uint8_t rsv[0x2c]; + uint8_t sp_ins[4032]; +} __rte_packed_end; + +#define SP_PROTOCOL_MAGIC_DATA 0xabcd +#define SP_PROTOCOL_MAGIC_OFFSET 0x4 + +/** Number of soft parser firmware bytes reported for debugging. */ +#define SP_PRINT_LEN 128 +/** Firmware bytes logged per debug line. */ +#define SP_DUMP_BYTES_PER_LINE 16 + +static void +fslmc_soft_parser_protocol_supported(void) +{ + int fd, i, pos = 0; + void *map_addr = NULL; + const struct dpaa2_parser_ccsr *parser_ccsr = NULL; + const uint16_t *magic_num; + char line[SP_DUMP_BYTES_PER_LINE * 3 + 1]; + + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd < 0) { + DPAA2_BUS_ERR("open \"/dev/mem\" ERROR(%d)", fd); + goto exit; + } + + map_addr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, + WRIOP_INGRESS_PARSER_PHY); + parser_ccsr = map_addr; + if (!parser_ccsr) { + DPAA2_BUS_ERR("Map 0x%" PRIx64 "(size=0x%zx) failed", + (uint64_t)WRIOP_INGRESS_PARSER_PHY, + sizeof(struct dpaa2_parser_ccsr)); + goto exit; + } + + DPAA2_BUS_DEBUG("Soft ParserID:0x%02x%02x, Rev:maj(%02x), min(%02x)", + parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, + parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); + + magic_num = (const void *)&parser_ccsr->sp_ins[SP_PROTOCOL_MAGIC_OFFSET]; + if (*magic_num == SP_PROTOCOL_MAGIC_DATA) { + fslmc_bus_info.sp_protocol = true; + DPAA2_BUS_INFO("Soft parser protocol support."); + DPAA2_BUS_DEBUG("First %d bytes of sp protocol firmware:", + SP_PRINT_LEN); + for (i = 0; i < SP_PRINT_LEN; i++) { + pos += snprintf(&line[pos], sizeof(line) - pos, + "%02x ", parser_ccsr->sp_ins[i]); + if ((i + 1) % SP_DUMP_BYTES_PER_LINE == 0) { + DPAA2_BUS_DEBUG("%s", line); + pos = 0; + } + } + if (pos) + DPAA2_BUS_DEBUG("%s", line); + } + +exit: + if (map_addr) + munmap(map_addr, sizeof(struct dpaa2_parser_ccsr)); + if (fd >= 0) + close(fd); +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_get_device_count) uint32_t rte_fslmc_get_device_count(enum rte_dpaa2_dev_type device_type) @@ -345,6 +433,7 @@ rte_fslmc_scan(void) DPAA2_BUS_ERR("Unable to open VFIO group directory"); goto scan_fail; } + fslmc_soft_parser_protocol_supported(); /* Scan the DPRC container object */ ret = scan_one_fslmc_device(group_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index e6ce29b2ea..fb1d01e209 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3735,6 +3735,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; + priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; + DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2662c358e4..cde2f5a9d3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -9,7 +9,6 @@ #include <string.h> #include <unistd.h> #include <stdarg.h> -#include <sys/mman.h> #include <rte_ethdev.h> #include <rte_log.h> @@ -22,9 +21,9 @@ #include <dpaa2_ethdev.h> #include <dpaa2_pmd_logs.h> +#include "dpaa2_parser_decode.h" static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -434,92 +433,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -3538,6 +3451,11 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); + return -ENOTSUP; + } + ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_GRE); if (ret) { @@ -3583,6 +3501,11 @@ dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, struct dpaa2_dev_priv *priv = dev->data->dev_private; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -3681,6 +3604,11 @@ dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("ROCEV2 flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -4000,6 +3928,11 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -4725,7 +4658,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, static int dpaa2_flow_item_convert(const struct rte_flow_item pattern[], - struct rte_dpaa2_flow_item **dpaa2_pattern) + struct rte_dpaa2_flow_item **dpaa2_pattern, int sp_protocol) { struct rte_dpaa2_flow_item *new_pattern; int num = 0, tunnel_start = 0; @@ -4737,7 +4670,7 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], } new_pattern = rte_malloc(NULL, sizeof(struct rte_dpaa2_flow_item) * num, - RTE_CACHE_LINE_SIZE); + RTE_CACHE_LINE_SIZE); if (!new_pattern) { DPAA2_PMD_ERR("Failed to alloc %d flow items", num); return -ENOMEM; @@ -4745,13 +4678,13 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], num = 0; while (pattern[num].type != RTE_FLOW_ITEM_TYPE_END) { - memcpy(&new_pattern[num].generic_item, &pattern[num], - sizeof(struct rte_flow_item)); + rte_memcpy(&new_pattern[num].generic_item, &pattern[num], + sizeof(struct rte_flow_item)); new_pattern[num].in_tunnel = 0; if (pattern[num].type == RTE_FLOW_ITEM_TYPE_VXLAN) tunnel_start = 1; - else if (tunnel_start) + else if (tunnel_start && sp_protocol) new_pattern[num].in_tunnel = 1; num++; } @@ -4788,7 +4721,8 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, if (ret) return ret; - ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern); + ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, + priv->sp_protocol); if (ret) return ret; @@ -5129,7 +5063,8 @@ dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, } static inline int -dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) +dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], + int sp_support) { unsigned int i, j, is_found = 0; int ret = 0; @@ -5153,7 +5088,7 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) } if (is_found) continue; - if (dpaa2_sp_loaded > 0) { + if (sp_support) { for (i = 0; i < sp_supported_num; i++) { if (sp_supported[i] == pattern[j].type) { is_found = 1; @@ -5232,7 +5167,7 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, goto not_valid_params; } /* Verify input pattern list */ - ret = dpaa2_dev_verify_patterns(pattern); + ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol); if (ret < 0) { DPAA2_PMD_ERR("Invalid pattern list is given"); rte_flow_error_set(error, EPERM, diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index f417edf52b..ccb4bbe7dc 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -128,6 +128,16 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; } } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 29/45] drivers: assign dpaa2 Rx CGID per traffic class 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (27 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 28/45] drivers: identify dpaa2 soft parser protocol Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 30/45] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta ` (21 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> RXQs in same TC should use same CGID for congestion set. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 3 +- drivers/net/dpaa2/dpaa2_ethdev.c | 252 ++++++++++++------------ drivers/net/dpaa2/dpaa2_ethdev.h | 3 +- 3 files changed, 126 insertions(+), 132 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f0bc9a3063..12216750a8 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -176,7 +176,6 @@ struct __rte_cache_aligned dpaa2_queue { uint32_t fqid; /*!< Unique ID of this queue */ uint16_t flow_id; /*!< To be used by DPAA2 framework */ uint8_t tc_index; /*!< traffic class identifier */ - uint8_t cgid; /*! < Congestion Group id for this queue */ uint64_t rx_pkts; uint64_t tx_pkts; uint64_t err_pkts; @@ -186,6 +185,8 @@ struct __rte_cache_aligned dpaa2_queue { /**Egress*/ struct qbman_result *cscn; }; + void *cfg; + uint8_t options; struct rte_event ev; dpaa2_queue_cb_dqrr_t *cb; dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index fb1d01e209..0835296ee2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP */ #include <time.h> @@ -682,6 +682,9 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) RTE_MAX_LCORE); dpaa2_queue_storage_free(dpaa2_q, RTE_MAX_LCORE); + if (dpaa2_q->cfg) + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; priv->rx_vq[i] = NULL; } /* cleanup tx queue cscn */ @@ -934,11 +937,12 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, struct fsl_mc_io *dpni = dev->process_private; bool dpcon_allocated = false; struct dpaa2_queue *dpaa2_q; - struct dpni_queue cfg; - uint8_t options = 0; - uint8_t flow_id; + struct dpni_queue *cfg; + struct dpni_taildrop taildrop; + uint8_t qopt = 0; + uint16_t flow_id; uint32_t bpid; - int i, ret; + int ret; PMD_INIT_FUNC_TRACE(); @@ -975,6 +979,10 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } + cfg = rte_zmalloc(NULL, sizeof(struct dpni_queue), 0); + if (!cfg) + return -ENOMEM; + dpaa2_q->cfg = cfg; dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1004,124 +1012,100 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, /*Get the flow id from given VQ id*/ flow_id = dpaa2_q->flow_id; - memset(&cfg, 0, sizeof(struct dpni_queue)); + memset(cfg, 0, sizeof(struct dpni_queue)); - options = options | DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_q); + qopt |= DPNI_QUEUE_OPT_USER_CTX; + cfg->user_context = (size_t)(dpaa2_q); /* napi: schedule the FQ to its DPCON once, when the channel is first * grabbed; never re-bound (the MC refuses scheduled->parked at runtime) */ if (dpcon_allocated) { - options |= DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpaa2_q->napi_dpcon->dpcon_id; - } - - /* check if a private cgr available. */ - for (i = 0; i < priv->max_cgs; i++) { - if (!priv->cgid_in_use[i]) { - priv->cgid_in_use[i] = 1; - break; - } + qopt |= DPNI_QUEUE_OPT_DEST; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpaa2_q->napi_dpcon->dpcon_id; } - if (i < priv->max_cgs) { - options |= DPNI_QUEUE_OPT_SET_CGID; - cfg.cgid = i; - dpaa2_q->cgid = cfg.cgid; + /** RXQs in same TC share same cgid.*/ + if (dpaa2_q->tc_index < priv->max_cgs) { + qopt |= DPNI_QUEUE_OPT_SET_CGID; + cfg->cgid = dpaa2_q->tc_index; + priv->cgid_in_use[dpaa2_q->tc_index]++; } else { - dpaa2_q->cgid = DPAA2_INVALID_CGID; + cfg->cgid = DPAA2_INVALID_CGID; } /*if ls2088 or rev2 device, enable the stashing */ if ((dpaa2_svr_family & 0xffff0000) != SVR_LS2080A) { - options |= DPNI_QUEUE_OPT_FLC; - cfg.flc.stash_control = true; - dpaa2_flc_stashing_clear_all(&cfg.flc.value); + qopt |= DPNI_QUEUE_OPT_FLC; + cfg->flc.stash_control = true; + dpaa2_flc_stashing_clear_all(&cfg->flc.value); if (priv->flags & DPAA2_DATA_STASHING_OFF) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 1; } else { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 0; } if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); } } + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, options, &cfg); + dpaa2_q->tc_index, flow_id, qopt, cfg); if (ret) { + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; DPAA2_PMD_ERR("Error in setting the rx flow: = %d", ret); goto err_free_dpcon; } dpaa2_q->nb_desc = nb_rx_desc; - - if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) { - struct dpni_taildrop taildrop; - + memset(&taildrop, 0, sizeof(struct dpni_taildrop)); + if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) taildrop.enable = 1; - /* Private CGR will use tail drop length as nb_rx_desc. - * for rest cases we can use standard byte based tail drop. - * There is no HW restriction, but number of CGRs are limited, - * hence this restriction is placed. - */ - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - /*enabling per rx queue congestion control */ - taildrop.threshold = nb_rx_desc; - taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; - taildrop.oal = 0; - DPAA2_PMD_DEBUG("Enabling CG Tail Drop on queue = %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - /*enabling per rx queue congestion control */ - taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; - taildrop.units = DPNI_CONGESTION_UNIT_BYTES; - taildrop.oal = CONG_RX_OAL; - DPAA2_PMD_DEBUG("Enabling Byte based Drop on queue= %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, - &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } - } else { /* Disable tail Drop */ - struct dpni_taildrop taildrop = {0}; - DPAA2_PMD_INFO("Tail drop is disabled on queue"); - - taildrop.enable = 0; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } + /* Private CGR will use tail drop length as nb_rx_desc * queues per TC. + * For rest cases we can use standard byte based tail drop. + * There is no HW restriction, but number of CGRs are limited, + * hence this restriction is placed. + */ + if (cfg->cgid != DPAA2_INVALID_CGID && + priv->cgid_in_use[dpaa2_q->tc_index] == 1) { + /*enabling per TC congestion control */ + taildrop.threshold = nb_rx_desc * priv->dist_queues; + taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; + taildrop.oal = 0; + DPAA2_PMD_DEBUG("%s CG Tail Drop on TC%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, + dpaa2_q->tc_index, cfg->cgid, &taildrop); + } else if (cfg->cgid == DPAA2_INVALID_CGID) { + /*enabling per rx queue congestion control */ + taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; + taildrop.units = DPNI_CONGESTION_UNIT_BYTES; + taildrop.oal = CONG_RX_OAL; + DPAA2_PMD_DEBUG("%s Byte based Drop on TC[%d].flow%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index, flow_id); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_QUEUE, DPNI_QUEUE_RX, + dpaa2_q->tc_index, flow_id, &taildrop); } + if (ret) { + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; + DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", ret); + return ret; + } + + dpaa2_q->options = qopt; dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; @@ -1150,8 +1134,8 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct fsl_mc_io *dpni = dev->process_private; struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; - uint8_t options = 0, flow_id; - uint16_t channel_id; + uint8_t qopt = 0; + uint16_t channel_id, flow_id; struct dpni_queue_id qid; uint32_t tc_id; int ret; @@ -1181,7 +1165,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, qopt, &tx_flow_cfg); if (ret) { DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", ret, dev->data->name, tc_id, flow_id); @@ -1190,7 +1174,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, &tx_flow_cfg, &qid); + dpaa2_q->flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1242,12 +1226,12 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; - options = options | DPNI_QUEUE_OPT_USER_CTX; + qopt |= DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, options, &tx_conf_cfg); + flow_id, qopt, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", tc_id, flow_id, ret); @@ -1296,30 +1280,29 @@ dpaa2_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id) struct dpaa2_queue *dpaa2_q = dev->data->rx_queues[rx_queue_id]; struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; struct fsl_mc_io *dpni = priv->eth_dev->process_private; - uint8_t options = 0; + uint8_t qopt = 0; int ret; - struct dpni_queue cfg; + struct dpni_queue *cfg = dpaa2_q->cfg; - memset(&cfg, 0, sizeof(struct dpni_queue)); PMD_INIT_FUNC_TRACE(); total_nb_rx_desc -= dpaa2_q->nb_desc; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - options = DPNI_QUEUE_OPT_CLEAR_CGID; - cfg.cgid = dpaa2_q->cgid; - - ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, dpaa2_q->flow_id, - options, &cfg); - if (ret) - DPAA2_PMD_ERR("Unable to clear CGR from q=%u err=%d", - dpaa2_q->fqid, ret); - priv->cgid_in_use[dpaa2_q->cgid] = 0; - dpaa2_q->cgid = DPAA2_INVALID_CGID; + if (cfg) { + if (cfg->cgid != DPAA2_INVALID_CGID) { + qopt = DPNI_QUEUE_OPT_CLEAR_CGID; + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, + DPNI_QUEUE_RX, dpaa2_q->tc_index, dpaa2_q->flow_id, + qopt, cfg); + if (ret) { + DPAA2_PMD_ERR("Unable to clear CGR from TC[%d].flow%d err=%d", + dpaa2_q->tc_index, dpaa2_q->flow_id, ret); + } + priv->cgid_in_use[cfg->cgid]--; + } + rte_free(cfg); + dpaa2_q->cfg = NULL; } - /* keep the DPCON on the FQ across a reconfigure; freed at dev_close */ if (dpaa2_q->napi_dpcon) dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); @@ -2833,10 +2816,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; + struct dpni_queue *cfg; uint8_t options, priority; int ret; + cfg = dpaa2_ethq->cfg; + if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) dpaa2_ethq->cb = dpaa2_dev_process_parallel_event; else if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) @@ -2849,15 +2834,19 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, priority = (RTE_EVENT_DEV_PRIORITY_LOWEST / queue_conf->ev.priority) * (dpcon->num_priorities - 1); - memset(&cfg, 0, sizeof(struct dpni_queue)); + if (!cfg) { + DPAA2_PMD_ERR("%s: %s-rxq%d was not setup yet!", + __func__, dev->data->name, eth_rx_queue_id); + return -EINVAL; + } options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpcon->dpcon_id; - cfg.destination.priority = priority; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpcon->dpcon_id; + cfg->destination.priority = priority; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) { options |= DPNI_QUEUE_OPT_HOLD_ACTIVE; - cfg.destination.hold_active = 1; + cfg->destination.hold_active = 1; } if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED && @@ -2896,16 +2885,16 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, } options |= DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_ethq); + cfg->user_context = (size_t)(dpaa2_ethq); ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, flow_id, options, cfg); if (ret) { DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); return ret; } - memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); + rte_memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); return 0; } @@ -2917,17 +2906,15 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; - uint8_t options; + struct dpni_queue *cfg; int ret; - memset(&cfg, 0, sizeof(struct dpni_queue)); - options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_NONE; + cfg = dpaa2_ethq->cfg; + cfg->destination.type = DPNI_DEST_NONE; + dpaa2_ethq->options &= ~DPNI_QUEUE_OPT_DEST; ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, dpaa2_ethq->flow_id, dpaa2_ethq->options, cfg); if (ret) DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); @@ -3547,10 +3534,15 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ - if (attr.options & DPNI_OPT_CUSTOM_CG) + if (attr.options & DPNI_OPT_CUSTOM_CG) { priv->max_cgs = attr.num_cgs; - else + if (priv->max_cgs < priv->num_rx_tc) { + DPAA2_PMD_WARN("DPNI%d has no enough cgids(%d) to set %d TCs", + hw_id, priv->max_cgs, priv->num_rx_tc); + } + } else { priv->max_cgs = 0; + } for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index f1d1967cd1..3c611652b1 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -478,7 +478,8 @@ struct dpaa2_dev_priv { uint8_t en_ordered; uint8_t en_loose_ordered; uint8_t max_cgs; - uint8_t cgid_in_use[MAX_RX_QUEUES]; + /** RXQs in same TC share same cgid.*/ + uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; /* Lowest priority FS flow id to receive flow steering miss frames. */ uint16_t default_flow; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 30/45] drivers: inherit dpaa2 rxq config for event queue 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (28 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 29/45] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 31/45] net/dpaa2: rename Rx queue flags Prashant Gupta ` (20 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The configuration parameter in event queue attachment should use flc and cgid configured in rxq setup. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 2 +- drivers/net/dpaa2/dpaa2_ethdev.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 12216750a8..f87bf51d09 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2025 NXP * */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0835296ee2..57c6e8e90b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -2815,11 +2815,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; + uint8_t flow_id; struct dpni_queue *cfg; uint8_t options, priority; int ret; + flow_id = dpaa2_ethq->flow_id; cfg = dpaa2_ethq->cfg; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 31/45] net/dpaa2: rename Rx queue flags 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (29 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 30/45] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 32/45] drivers: rework dpaa2 Tx confirmation Prashant Gupta ` (19 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change; it prepares the flag namespace for the Tx confirmation rework that follows. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 4 ++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 57c6e8e90b..15a886b3e8 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -547,7 +547,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, qopt |= DPNI_QUEUE_OPT_FLC; cfg->flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg->flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg->flc.value); dpaa2_q->data_stashing_off = 1; @@ -1499,7 +1499,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3462,7 +3462,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3592,7 +3592,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 3c611652b1..28623dc37d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,9 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index ccb4bbe7dc..a03e3fd8db 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -870,7 +870,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1142,7 +1142,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 32/45] drivers: rework dpaa2 Tx confirmation 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (30 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 31/45] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 33/45] net/dpaa2: ptp enhancements Prashant Gupta ` (18 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Mbufs released by Tx confirmation may come from any mempool, so use the RTE mbuf free API instead of returning the buffers directly to the bman pool. The FD FLC field now carries the Tx mbuf pointer so that the confirmation callback can release it to either the platform pool or an external pool. Absolute and dynamic Tx confirmation become independent settings, giving three Tx modes: 1) No confirmation (default). Suited to traffic that is mostly sent from the platform pool. For the few packets from other pools the driver allocates a platform buffer, copies the data and frees the original. 2) Absolute confirmation. Suited to traffic mostly sent from non platform pools. Every Tx packet raises a confirmation, configured at queue setup, and the callback frees the packet. 3) Dynamic confirmation. Confirmation is raised only for packets from non platform pools; the driver marks each packet accordingly at runtime. This suits a roughly even mix of platform and non platform buffers. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 2 +- drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 63 +- drivers/net/dpaa2/dpaa2_ethdev.h | 37 +- drivers/net/dpaa2/dpaa2_ptp.c | 4 +- drivers/net/dpaa2/dpaa2_rxtx.c | 1511 ++++++++---------- 7 files changed, 751 insertions(+), 873 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f87bf51d09..b3aad85d06 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -198,6 +198,7 @@ struct __rte_cache_aligned dpaa2_queue { uint16_t tm_sw_td; /*!< TM software taildrop */ uint64_t offloads; uint64_t lpbk_cntx; + int32_t ts_to_cnfd; uint8_t data_stashing_off; /* NAPI rx-interrupt: per-queue DPCON bound to this FQ at dev_start * (DEST_DPCON, static); the polling worker points the channel's CDAN at diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c index 26ad105c73..fee96b3529 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c @@ -484,7 +484,7 @@ dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, */ /* ... rx buffer layout ... */ - if (priv->flags & DPAA2_TX_DYNAMIC_CONF_ENABLE) { + if (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) { int out_min_hdr_room, in_min_hdr_room; /** Additional headroom layout for IPSec with TX configure * dynamic enabled. diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h index a670098958..b06fa3f644 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019,2022,2024 NXP + * Copyright 2016,2019,2022,2024-2026 NXP * */ @@ -281,6 +281,10 @@ struct dpaa2_faead { /*UPD (Update prepended data)*/ #define DPAA2_ANNOT_FAEAD_UPD 0x00000010 +#define DPAA2_TX_CONFIRM_ENABLE \ + (DPAA2_ANNOT_FAEAD_A4V | DPAA2_ANNOT_FAEAD_EBDD | \ + DPAA2_ANNOT_FAEAD_EBDDV) + /* Debug frame, otherwise supposed to be discarded */ #define DPAA2_ETH_FAS_DISC 0x80000000 /* MACSEC frame */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 15a886b3e8..61b7ae138c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -34,6 +34,8 @@ #define DRIVER_LOOPBACK_MODE "drv_loopback" #define DRIVER_NO_PREFETCH_MODE "drv_no_prefetch" #define DRIVER_TX_CONF "drv_tx_conf" +#define DRIVER_TX_DYNAMIC_CONF "drv_tx_dyn_conf" +#define DRIVER_TX_DYNAMIC_CONF_PREFETCH "drv_tx_dyn_conf_pre" #define DRIVER_RX_PARSE_ERR_DROP "drv_rx_parse_drop" #define DRIVER_ERROR_QUEUE "drv_err_queue" #define DRIVER_NO_TAILDROP "drv_no_taildrop" @@ -522,7 +524,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (priv->flags & DPAA2_TX_CONF_ENABLE) + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else tot_queues = priv->nb_rx_queues + priv->nb_tx_queues; @@ -578,7 +580,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; @@ -693,7 +695,7 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) rte_free(dpaa2_q->cscn); priv->tx_vq[i] = NULL; } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /* cleanup tx conf queue storage */ for (i = 0; i < priv->nb_tx_queues; i++) { dpaa2_q = priv->tx_conf_vq[i]; @@ -1143,6 +1145,13 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, PMD_INIT_FUNC_TRACE(); + /* Tx deferred start is not supported */ + if (tx_conf->tx_deferred_start) { + DPAA2_PMD_ERR("%s:Tx deferred start not supported", + dev->data->name); + return -EINVAL; + } + dpaa2_q->nb_desc = UINT16_MAX; dpaa2_q->offloads = tx_conf->offloads; @@ -1222,7 +1231,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->cb_eqresp_free = dpaa2_dev_free_eqresp_buf; dev->data->tx_queues[tx_queue_id] = dpaa2_q; - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; @@ -3585,10 +3594,22 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) DPAA2_PMD_INFO("DPDK IEEE1588 is enabled"); priv->flags |= DPAA2_TX_CONF_ENABLE; #endif + priv->tx_conf_type = DPAA2_TX_NO_CONF; + /* Used with ``fslmc:dpni.1,drv_tx_conf=1`` */ if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_CONF)) { - priv->flags |= DPAA2_TX_CONF_ENABLE; - DPAA2_PMD_INFO("TX_CONF Enabled"); + priv->tx_conf_type = DPAA2_TX_ABSOLUTE_CONF; + DPAA2_PMD_INFO("TX_ABSOLUTE_CONF Enabled"); + } else if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_DYNAMIC_CONF)) { + priv->tx_conf_type = DPAA2_TX_DYNAMIC_CONF; + DPAA2_PMD_INFO("TX_DYNAMIC_CONF Enabled"); + priv->flags |= DPAA2_TX_PREFETCH_DYNAMIC_CONF; + if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_DYNAMIC_CONF_PREFETCH)) + priv->flags &= ~DPAA2_TX_PREFETCH_DYNAMIC_CONF; + + DPAA2_PMD_INFO("Tx dynamic prefetch confirm %s", + (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) ? + "enabled" : "disabled"); } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { @@ -3603,7 +3624,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); @@ -3614,7 +3635,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->num_channels; i++) { /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) { ret = dpni_set_tx_confirmation_mode(dpni_dev, CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); } else { @@ -3651,34 +3672,22 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) /* ... tx buffer layout ... */ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | - DPNI_BUF_LAYOUT_OPT_TIMESTAMP; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; layout.pass_timestamp = true; - } else { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; } + layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, &layout); + DPNI_QUEUE_TX, &layout); if (ret) { DPAA2_PMD_ERR("Error (%d) in setting tx buffer layout", ret); goto init_err; } - - /* ... tx-conf and error buffer layout ... */ - memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; - layout.pass_timestamp = true; - } - layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; - layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX_CONFIRM, &layout); + DPNI_QUEUE_TX_CONFIRM, &layout); if (ret) { - DPAA2_PMD_ERR("Error (%d) in setting tx-conf buffer layout", - ret); + DPAA2_PMD_ERR("Error (%d) in setting tx conf buffer layout", ret); goto init_err; } @@ -3979,6 +3988,8 @@ RTE_PMD_REGISTER_PARAM_STRING(NET_DPAA2_PMD_DRIVER_NAME, DRIVER_LOOPBACK_MODE "=<int> " DRIVER_NO_PREFETCH_MODE "=<int>" DRIVER_TX_CONF "=<int>" + DRIVER_TX_DYNAMIC_CONF "=<int>" + DRIVER_TX_DYNAMIC_CONF_PREFETCH "=<int>" DRIVER_RX_PARSE_ERR_DROP "=<int>" DRIVER_ERROR_QUEUE "=<int>" DRIVER_NO_TAILDROP "=<int>" diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 28623dc37d..c6a8b4f595 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -91,18 +91,14 @@ #define DPAA2_TX_DPNI_LOOPBACK_MODE RTE_BIT32(7) -/* Tx confirmation enabled */ -#define DPAA2_TX_CONF_ENABLE RTE_BIT32(8) +#define DPAA2_TX_PREFETCH_DYNAMIC_CONF RTE_BIT32(8) -/* Tx dynamic confirmation enabled, - * only valid with Tx confirmation enabled. - */ -#define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(9) + +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -/* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) +#define DPAA2_RX_SCHED_STRICT_ORDER_FLAG RTE_BIT32(11) -#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ @@ -451,6 +447,12 @@ struct dpaa2_dev_meter { uint32_t policy_id; }; +enum dpaa2_tx_conf_type { + DPAA2_TX_NO_CONF, + DPAA2_TX_ABSOLUTE_CONF, + DPAA2_TX_DYNAMIC_CONF +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -466,6 +468,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + enum dpaa2_tx_conf_type tx_conf_type; int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; @@ -510,10 +513,10 @@ struct dpaa2_dev_priv { int rx_ts_offset; uint64_t rx_ts_flag; - /* stores pointer to next tx_conf queue that should be processed, + /* stores next tx queue to be confirmed that should be processed, * it corresponds to last packet transmitted */ - struct dpaa2_queue *next_tx_conf_queue; + struct dpaa2_queue *next_txq_to_cnf; struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; @@ -531,6 +534,8 @@ struct dpaa2_dev_priv { uint64_t cnt_idx_iova, cnt_values_iova; uint64_t mc_rev; + struct rte_mempool *tx_sg_pool; + struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; LIST_HEAD(, dpaa2_dev_meter_profile) profiles; @@ -646,7 +651,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); -uint16_t dpaa2_dev_tx_conf(void *queue) __rte_unused; +uint16_t dpaa2_dev_tx_conf(void *txq, int drain); int dpaa2_timesync_enable(struct rte_eth_dev *dev); int dpaa2_timesync_disable(struct rte_eth_dev *dev); @@ -663,6 +668,14 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); + +__rte_internal +struct rte_mbuf *__rte_hot +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); +__rte_internal +struct rte_mbuf *__rte_hot +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); + int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index 751e558c73..c845291c68 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -111,9 +111,9 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; - if (priv->next_tx_conf_queue) { + if (priv->next_txq_to_cnf) { while (!priv->tx_timestamp) - dpaa2_dev_tx_conf(priv->next_tx_conf_queue); + dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); } else { return -1; } diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index a03e3fd8db..4512c8cf00 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2026 NXP * */ @@ -75,6 +75,23 @@ dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, DPAA2_RESET_FD_FLC(_fd); \ } while (0) +/* Build a contiguous FD which is returned on the Tx confirmation queue. + * The buffer is not released by the hardware, so an invalid buffer pool + * ID is programmed and the mbuf is carried in the FLC to be freed once + * the confirmation is dequeued. + */ +static inline void +dpaa2_mbuf_to_conf_contig_fd(struct rte_mbuf *mbuf, struct qbman_fd *fd) +{ + DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(mbuf)); + DPAA2_SET_FD_LEN(fd, mbuf->data_len); + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + DPAA2_SET_FD_OFFSET(fd, mbuf->data_off); + DPAA2_SET_FD_FRC(fd, 0); + DPAA2_RESET_FD_CTRL(fd); + DPAA2_SET_FD_FLC(fd, mbuf); +} static inline void dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, @@ -98,7 +115,6 @@ dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, m->hash.rss); } } - static void __rte_hot dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, struct rte_mbuf *m, const struct qbman_fd *fd, @@ -237,13 +253,6 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, "(4)=0x%" PRIx64 "\t", annotation->word3, annotation->word4); -#if defined(RTE_LIBRTE_IEEE1588) - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) { - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST; - } -#endif - if (BIT_ISSET_AT_POS(annotation->word3, L2_VLAN_1_PRESENT)) { vlan_tci = rte_pktmbuf_mtod_offset(mbuf, uint16_t *, (VLAN_TCI_OFFSET_1(annotation->word5) >> 16)); @@ -367,13 +376,14 @@ dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, return dpaa2_dev_rx_parse_slow(mbuf, annotation); } -static inline struct rte_mbuf *__rte_hot +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_sg_fd_to_mbuf) +struct rte_mbuf *__rte_hot dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; - size_t sg_addr, fd_addr; + size_t fd_addr; int i = 0; - void *hw_annot_addr; + void *hw_annot_addr, *sg_addr; struct rte_mbuf *first_seg, *next_seg, *cur_seg, *temp; fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); @@ -383,7 +393,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) sgt = (struct qbman_sge *)(fd_addr + DPAA2_GET_FD_OFFSET(fd)); sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); /* First Scatter gather entry */ first_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, @@ -413,8 +423,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) cur_seg = first_seg; while (!DPAA2_SG_IS_FINAL(sge) && i < DPAA2_MAX_SGS) { sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR( - DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); next_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, rte_dpaa2_bpid_info[DPAA2_GET_FLE_BPID(sge)].meta_data_size); next_seg->buf_addr = (uint8_t *)sg_addr; @@ -442,7 +451,8 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return (void *)first_seg; } -static inline struct rte_mbuf *__rte_hot +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_fd_to_mbuf) +struct rte_mbuf *__rte_hot dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); @@ -499,119 +509,296 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return mbuf; } -static int __rte_noinline __rte_hot -eth_mbuf_to_sg_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *free_buf, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +static void dpaa2_dev_tx_enable_tstamp(struct qbman_fd *fd) { - struct rte_mbuf *cur_seg = mbuf, *mi, *temp; - struct qbman_sge *sgt, *sge = NULL; - int i, offset = 0; + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); -#ifdef RTE_LIBRTE_IEEE1588 - /* annotation area for timestamp in first buffer */ - offset = 0x64; -#endif - if (RTE_MBUF_DIRECT(mbuf) && - (mbuf->data_off > (mbuf->nb_segs * sizeof(struct qbman_sge) - + offset))) { - temp = mbuf; - if (rte_mbuf_refcnt_read(temp) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - fd->simple.bpid_offset = 0; + /* Set frame annotation status field as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FASV; + + /* Set frame annotation egress action descriptor as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; + + /* Set Annotation Length as 128B */ + (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD); +} + +static inline struct rte_mbuf * +dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) +{ + struct rte_mbuf *mc = rte_pktmbuf_alloc(mp); + + if (!mc) + return NULL; + if ((mc->data_off + sgm->data_len) > mc->buf_len) { + rte_pktmbuf_free(mc); + return NULL; + } + rte_memcpy(rte_pktmbuf_mtod(mc, void *), + rte_pktmbuf_mtod(sgm, void *), sgm->data_len); + mc->pkt_len = sgm->data_len; + mc->data_len = sgm->data_len; + mc->next = NULL; + + return mc; +} + +static inline void +dpaa2_dev_tx_config_dynamic_confirm(struct qbman_fd *fd, + struct dpaa2_queue *txq, int enable, int tstamp) +{ + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + + if (tstamp) { + DPAA2_SET_FD_FRC(fd, + DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV | DPAA2_FD_FRC_FASV); + fd->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + } else { + DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV); + } + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + if (enable) { + fd_faead->fqid = txq->tx_conf_queue->fqid; + fd_faead->ctrl = DPAA2_TX_CONFIRM_ENABLE; + if (tstamp) { + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | + DPAA2_ANNOT_FAEAD_UPD); + } + } else { + fd_faead->fqid = 0; + fd_faead->ctrl &= (~DPAA2_TX_CONFIRM_ENABLE); + } +} + +static int +dpaa2_dev_tx_no_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf, + struct rte_mempool *hw_mp) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg, *mi, *prev, *copy_mbuf; + + cur_seg = mbuf; + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + mi = rte_mbuf_from_indirect(cur_seg); + if (rte_mbuf_refcnt_read(mi) > 1) + rte_mbuf_refcnt_update(mi, -1); + else + rte_pktmbuf_free_seg(mi); + copy_mbuf->next = cur_seg->next; + if (prev) + prev->next = copy_mbuf; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + if (unlikely(RTE_MBUF_HAS_EXTBUF(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index)) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + + copy_mbuf->next = cur_seg->next; + + if (prev) + prev->next = copy_mbuf; + if (rte_mbuf_refcnt_read(cur_seg) > 1) + rte_mbuf_refcnt_update(cur_seg, -1); + else + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + if (unlikely(rte_mbuf_refcnt_read(cur_seg) > 1)) { + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + rte_mbuf_refcnt_update(cur_seg, -1); + } else { + DPAA2_SET_FLE_BPID(sge, mempool_to_bpid(cur_seg->pool)); + } + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); + + return 0; +} + +static void +dpaa2_dev_tx_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg = mbuf, *mi, *prev; + + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + mi = rte_mbuf_from_indirect(cur_seg); + mi->next = cur_seg->next; + if (prev) + prev->next = mi; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = mi; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); +} + +static int __rte_noinline __rte_hot +dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf, int tstamp) +{ + struct rte_mbuf *cur_seg = mbuf, *sg_mbuf; + struct qbman_sge *sgt; + int offset = 0, ret, need_dyconf = false, need_conf = false; + uint16_t nb_segs = mbuf->nb_segs; + uint32_t sg_size = nb_segs * sizeof(struct qbman_sge); + struct rte_mempool *mp; + struct dpaa2_dev_priv *priv = txq->eth_data->dev_private; + + if (conf == DPAA2_TX_DYNAMIC_CONF) { + while (cur_seg) { + if (!RTE_MBUF_DIRECT(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index || + rte_mbuf_refcnt_read(cur_seg) > 1 || tstamp) { + need_dyconf = true; + break; + } + cur_seg = cur_seg->next; + } + cur_seg = mbuf; + } + if (need_dyconf || conf == DPAA2_TX_ABSOLUTE_CONF) + need_conf = true; + + if (need_dyconf || tstamp) + offset = DPAA2_FD_PTA_SIZE + DPAA2_DYN_TX_MIN_FD_OFFSET; + + if (mbuf->pool->ops_index == hw_mp->ops_index && + RTE_MBUF_DIRECT(mbuf) && + mbuf->data_off > RTE_ALIGN(sg_size + offset, 8)) { + sg_mbuf = mbuf; + mp = mbuf->pool; + if (need_conf) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); DPAA2_SET_FD_IVP(fd); - rte_mbuf_refcnt_update(temp, -1); } else { - DPAA2_SET_ONLY_FD_BPID(fd, bpid); + if (unlikely(rte_mbuf_refcnt_read(sg_mbuf) > 1)) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + rte_mbuf_refcnt_update(sg_mbuf, -1); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(mp)); + } + } #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif - } DPAA2_SET_FD_OFFSET(fd, offset); } else { - temp = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); - if (temp == NULL) { + sg_mbuf = NULL; + if (priv->tx_sg_pool) + sg_mbuf = rte_pktmbuf_alloc(priv->tx_sg_pool); + if (!sg_mbuf) { DPAA2_PMD_DP_DEBUG("No memory to allocate S/G table"); return -ENOMEM; } - DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); - DPAA2_SET_FD_OFFSET(fd, temp->data_off); + if (need_conf) { + if (need_dyconf) + sg_mbuf->data_off = RTE_ALIGN(offset, 8); + else + sg_mbuf->data_off = RTE_PKTMBUF_HEADROOM; + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(priv->tx_sg_pool)); + } + DPAA2_SET_FD_OFFSET(fd, sg_mbuf->data_off); + offset = sg_mbuf->data_off; #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif } - DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(temp)); + + /*Set Scatter gather table and Scatter gather entries*/ + sgt = (void *)((size_t)sg_mbuf->buf_addr + offset); + DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(sg_mbuf)); DPAA2_SET_FD_LEN(fd, mbuf->pkt_len); DPAA2_FD_SET_FORMAT(fd, qbman_fd_sg); DPAA2_RESET_FD_FRC(fd); DPAA2_RESET_FD_CTRL(fd); - DPAA2_RESET_FD_FLC(fd); - /*Set Scatter gather table and Scatter gather entries*/ - sgt = (struct qbman_sge *)( - (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) - + DPAA2_GET_FD_OFFSET(fd)); + if (need_conf) + DPAA2_SET_FD_FLC(fd, sg_mbuf); + else + DPAA2_RESET_FD_FLC(fd); + if (need_dyconf) + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); + else if (tstamp) + dpaa2_dev_tx_enable_tstamp(fd); - for (i = 0; i < mbuf->nb_segs; i++) { - sge = &sgt[i]; - /*Resetting the buffer pool id and offset field*/ - sge->fin_bpid_offset = 0; - DPAA2_SET_FLE_ADDR(sge, rte_pktmbuf_iova(cur_seg)); - sge->length = cur_seg->data_len; - if (RTE_MBUF_DIRECT(cur_seg)) { - /* if we are using inline SGT in same buffers - * set the FLE FMT as Frame Data Section - */ - if (temp == cur_seg) { - DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); - DPAA2_SET_FLE_IVP(sge); - } else { - if (rte_mbuf_refcnt_read(cur_seg) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - rte_mbuf_refcnt_update(cur_seg, -1); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(cur_seg->pool)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)cur_seg), - (void **)&cur_seg, 1, 0); -#endif - } - } - } else if (RTE_MBUF_HAS_EXTBUF(cur_seg)) { - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FLE_IVP(sge); - } else { - /* Get owner MBUF from indirect buffer */ - mi = rte_mbuf_from_indirect(cur_seg); - if (rte_mbuf_refcnt_read(mi) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * owner buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(mi->pool)); - rte_mbuf_refcnt_update(mi, 1); - } - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - } - cur_seg = cur_seg->next; + if (cur_seg != sg_mbuf && need_conf) + sg_mbuf->next = cur_seg; + + if (need_conf) { + dpaa2_dev_tx_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, sg_mbuf); + } else { + ret = dpaa2_dev_tx_no_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, + sg_mbuf, hw_mp); + if (ret) + return ret; } - DPAA2_SG_SET_FINAL(sge, true); + if (dy_conf && need_dyconf) + *dy_conf = true; + return 0; } @@ -632,101 +819,59 @@ dpaa2_dev_prefetch_next_psr(const struct qbman_result *dq) rte_prefetch0(&annotation->word3); } -static void -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) __rte_unused; - -static void __rte_noinline __rte_hot -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +static int __rte_noinline __rte_hot +dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf, int tstamp) { - DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, bpid); + int need_dyconf = false, need_conf = false; + struct rte_mbuf *mi; + struct rte_mbuf *copy_mbuf; + int ret = 0; - DPAA2_PMD_DP_DEBUG("mbuf =%p, mbuf->buf_addr =%p, off = %d," - "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", - mbuf, mbuf->buf_addr, mbuf->data_off, - DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd)); - if (RTE_MBUF_DIRECT(mbuf)) { + if (unlikely(RTE_MBUF_CLONED(mbuf))) { + mi = rte_mbuf_from_indirect(mbuf); if (rte_mbuf_refcnt_read(mbuf) > 1) { - DPAA2_SET_FD_IVP(fd); rte_mbuf_refcnt_update(mbuf, -1); + } else { + rte_pktmbuf_init(mbuf->pool, NULL, mbuf, 0); + rte_pktmbuf_free(mbuf); } -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - else - rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf), - (void **)&mbuf, 1, 0); -#endif - } else if (RTE_MBUF_HAS_EXTBUF(mbuf)) { - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FD_IVP(fd); + mbuf = mi; + } + if (conf == DPAA2_TX_DYNAMIC_CONF && + (mbuf->pool->ops_index != hw_mp->ops_index || + RTE_MBUF_HAS_EXTBUF(mbuf) || + rte_mbuf_refcnt_read(mbuf) > 1 || tstamp)) + need_dyconf = true; + if (conf == DPAA2_TX_ABSOLUTE_CONF || need_dyconf) + need_conf = true; + + if (need_conf) { + dpaa2_mbuf_to_conf_contig_fd(mbuf, fd); + } else if (mbuf->pool->ops_index == hw_mp->ops_index) { + DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, mempool_to_bpid(mbuf->pool)); } else { - struct rte_mbuf *mi; - - mi = rte_mbuf_from_indirect(mbuf); - if (rte_mbuf_refcnt_read(mi) > 1) - DPAA2_SET_FD_IVP(fd); - else - rte_mbuf_refcnt_update(mi, 1); - - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(mbuf, hw_mp); + if (!copy_mbuf) { + ret = -ENOMEM; + goto quit; + } + DPAA2_MBUF_TO_CONTIG_FD(copy_mbuf, fd, mempool_to_bpid(hw_mp)); +quit: + rte_pktmbuf_free(mbuf); } -} - -static inline int __rte_hot -eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, uint16_t bpid) -{ - struct rte_mbuf *m; - void *mb = NULL; - if (rte_dpaa2_mbuf_alloc_bulk( - rte_dpaa2_bpid_info[bpid].bp_list->mp, &mb, 1)) { - DPAA2_PMD_DP_DEBUG("Unable to allocated DPAA2 buffer"); - return -1; + if (need_dyconf) { + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); + if (dy_conf) + *dy_conf = true; + } else if (tstamp) { + dpaa2_dev_tx_enable_tstamp(fd); } - m = (struct rte_mbuf *)mb; - memcpy((char *)m->buf_addr + mbuf->data_off, - (void *)((char *)mbuf->buf_addr + mbuf->data_off), - mbuf->pkt_len); - - /* Copy required fields */ - m->data_off = mbuf->data_off; - m->ol_flags = mbuf->ol_flags; - m->packet_type = mbuf->packet_type; - m->tx_offload = mbuf->tx_offload; - - DPAA2_MBUF_TO_CONTIG_FD(m, fd, bpid); - -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)m), - (void **)&m, 1, 0); -#endif - DPAA2_PMD_DP_DEBUG( - "mbuf: %p, BMAN buf addr: %p, fdaddr: %" PRIx64 ", bpid: %d," - " meta: %d, off: %d, len: %d", - (void *)mbuf, - mbuf->buf_addr, - DPAA2_GET_FD_ADDR(fd), - DPAA2_GET_FD_BPID(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_OFFSET(fd), - DPAA2_GET_FD_LEN(fd)); -return 0; + return ret; } static void @@ -812,7 +957,6 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) dpaa2_dev_rx_parse_offset(priv, mbuf, fd); dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); - DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd), @@ -1237,12 +1381,6 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1273,150 +1411,208 @@ dpaa2_dev_rx_channel(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) return dpaa2_dev_rx_common(queue, bufs, nb_pkts, true); } -uint16_t dpaa2_dev_tx_conf(void *queue) +static inline int +dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, + struct rte_mbuf *mbuf) { - /* Function receive frames for a given device and VQ */ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct qbman_result *dq_storage; + while (mbuf) { + if (mbuf->pool != mp) + return false; + mbuf = mbuf->next; + } + + return true; +} + +uint16_t dpaa2_dev_tx_conf(void *txq, int drain) +{ + /* Function receive frames for a given device and VQ*/ + struct dpaa2_queue *dpaa2_txq = txq; + struct dpaa2_queue *dpaa2_q = dpaa2_txq->tx_conf_queue; + struct qbman_result *dq_storage, *dq_storage1 = NULL; uint32_t fqid = dpaa2_q->fqid; - int ret, num_tx_conf = 0; - uint8_t pending, status, num_pulled; + int ret, pull_size, total = 0, bulk_free; + uint8_t pending, status, idx, buf_idx; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; - struct qbman_release_desc releasedesc; - uint32_t bpid; - uint64_t buf; -#if defined(RTE_LIBRTE_IEEE1588) - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_annot_hdr *annotation; - void *v_addr; - struct rte_mbuf *mbuf; -#endif + struct queue_storage_info_t *q_storage; + struct qbman_result *rst; - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); + struct rte_mbuf *mbufs[dpaa2_dqrr_size]; + struct rte_mempool *mp = NULL; + #define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + +conf_again: + bulk_free = true; + idx = 0; + q_storage = dpaa2_q->q_storage[rte_lcore_id()]; + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); + DPAA2_PMD_ERR("Failure in affining portal"); return 0; } } - swp = DPAA2_PER_LCORE_PORTAL; - do { - dq_storage = dpaa2_q->q_storage[0]->dq_storage[0]; + swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + pull_size = dpaa2_dqrr_size; + if (unlikely(!q_storage->active_dqs)) { + q_storage->toggle = 0; + dq_storage = q_storage->dq_storage[q_storage->toggle]; + q_storage->last_num_pkts = pull_size; qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, + q_storage->last_num_pkts); qbman_pull_desc_set_fq(&pulldesc, fqid); qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - - qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size); - + DPAA2_VADDR_TO_IOVA(dq_storage), 1); + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } while (1) { if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued." - "QBMAN is busy"); + DPAA2_PMD_DP_DEBUG("QBMAN is busy (1)"); /* Portal was busy, try again */ continue; } break; } + q_storage->active_dqs = dq_storage; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage); + } - rte_prefetch0((void *)((size_t)(dq_storage + 1))); - /* Check if the previous issued command is completed. */ - while (!qbman_check_command_complete(dq_storage)) - ; - - num_pulled = 0; - pending = 1; - do { - /* Loop until the dq_storage is updated with - * new token by QBMAN - */ - while (!qbman_check_new_result(dq_storage)) - ; - rte_prefetch0((void *)((size_t)(dq_storage + 2))); - /* Check whether Last Pull command is Expired and - * setting Condition for Loop termination - */ - if (qbman_result_DQ_is_pull_complete(dq_storage)) { - pending = 0; - /* Check for valid frame. */ - status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & - QBMAN_DQ_STAT_VALIDFRAME) == 0)) - continue; - } - if (dpaa2_svr_family != SVR_LX2160A) - /** Packet type is parsed from FRC for LX2160A.*/ - dpaa2_dev_prefetch_next_psr(dq_storage); + dq_storage = q_storage->active_dqs; + rte_prefetch0((void *)(dq_storage)); + rte_prefetch0((void *)(dq_storage + 1)); - fd = qbman_result_DQ_fd(dq_storage); - bpid = DPAA2_GET_FD_BPID(fd); + /* Prepare next pull descriptor. This will give space for the + * prefetching done on DQRR entries + */ + q_storage->toggle ^= 1; + dq_storage1 = q_storage->dq_storage[q_storage->toggle]; + qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, pull_size); + qbman_pull_desc_set_fq(&pulldesc, fqid); + qbman_pull_desc_set_storage(&pulldesc, dq_storage1, + DPAA2_VADDR_TO_IOVA(dq_storage1), 1); - /* Create a release descriptor required for releasing - * buffers into QBMAN - */ - qbman_release_desc_clear(&releasedesc); - qbman_release_desc_set_bpid(&releasedesc, bpid); + /* Check if the previous issued command is completed. + * Also seems like the SWP is shared between the Ethernet Driver + * and the SEC driver. + */ + while (!qbman_check_command_complete(dq_storage)) + ; + if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id)) + clear_swp_active_dqs(q_storage->active_dpio_id); - buf = DPAA2_GET_FD_ADDR(fd); - /* feed them to bman */ - do { - ret = qbman_swp_release(swp, &releasedesc, - &buf, 1); - } while (ret == -EBUSY); + pending = 1; - dq_storage++; - num_tx_conf++; - num_pulled++; -#if defined(RTE_LIBRTE_IEEE1588) - v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); - mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); - - if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - annotation = (struct dpaa2_annot_hdr *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE); - priv->tx_timestamp = annotation->word2; - } -#endif - } while (pending); + do { + /* Loop until the dq_storage is updated with + * new token by QBMAN + */ + while (!qbman_check_new_result(dq_storage)) + ; + rte_prefetch0((void *)(dq_storage + 2)); + /* Check whether Last Pull command is Expired and + * setting Condition for Loop termination + */ + if (qbman_result_DQ_is_pull_complete(dq_storage)) { + pending = 0; + /* Check for valid frame. */ + status = qbman_result_DQ_flags(dq_storage); + if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) + continue; + } - /* Last VDQ provided all packets and more packets are requested */ - } while (num_pulled == dpaa2_dqrr_size); + fd = qbman_result_DQ_fd(dq_storage); + mbufs[idx] = (void *)DPAA2_GET_FD_FLC(fd); + if (unlikely(!mp)) + mp = mbufs[idx]->pool; + if (unlikely(rte_mbuf_refcnt_read(mbufs[idx]) > 1)) + bulk_free = false; + if (bulk_free && + !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) + bulk_free = false; + idx++; + dq_storage++; + if (idx >= dpaa2_dqrr_size) + break; + } while (pending); - dpaa2_q->rx_pkts += num_tx_conf; + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } + /* issue a volatile dequeue command for next pull */ + while (1) { + if (qbman_swp_pull(swp, &pulldesc)) { + DPAA2_PMD_DP_DEBUG("QBMAN is busy (2)"); + continue; + } + break; + } + q_storage->active_dqs = dq_storage1; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage1); - return num_tx_conf; -} -#ifdef RTE_LIBRTE_IEEE1588 -/* Configure the egress frame annotation for timestamp update */ -static void enable_tx_tstamp(struct qbman_fd *fd) -{ - struct dpaa2_faead *fd_faead; + if (bulk_free) { + rte_pktmbuf_free_bulk(mbufs, idx); + } else { + for (buf_idx = 0; buf_idx < idx; buf_idx++) { + if (rte_mbuf_refcnt_read(mbufs[buf_idx]) > 1) + rte_mbuf_refcnt_update(mbufs[buf_idx], -1); + else + rte_pktmbuf_free(mbufs[buf_idx]); + } + } - /* Set frame annotation status field as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FASV; + dpaa2_q->rx_pkts += idx; + total += idx; + if (drain && pending) + goto conf_again; - /* Set frame annotation egress action descriptor as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; + return total; +} - /* Set Annotation Length as 128B */ - (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; +static inline int +dpaa2_dev_tx_fast_mbuf_to_fd(struct rte_eth_dev_data *dev, + struct rte_mbuf *buf, struct qbman_fd *fd, + enum dpaa2_tx_conf_type conf) +{ + struct rte_mempool *mp = buf->pool; + struct dpaa2_dev_priv *priv = dev->dev_private; + + if (likely(RTE_MBUF_DIRECT(buf) && + mp && mp->ops_index == + priv->bp_list->dpaa2_ops_index && + buf->nb_segs == 1 && + rte_mbuf_refcnt_read(buf) == 1)) { + if (unlikely(buf->next)) { + DPAA2_PMD_WARN("Single mbuf has next segment(%p)", + buf->next); + } + if (unlikely(conf == DPAA2_TX_ABSOLUTE_CONF)) + dpaa2_mbuf_to_conf_contig_fd(buf, fd); + else + DPAA2_MBUF_TO_CONTIG_FD(buf, fd, mempool_to_bpid(mp)); +#ifdef RTE_LIBRTE_MEMPOOL_DEBUG + rte_mempool_check_cookies(rte_mempool_from_obj(buf), + (void **)&buf, 1, 0); +#endif + return 0; + } - /* enable update of confirmation frame annotation */ - fd_faead = (struct dpaa2_faead *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); - fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | - DPAA2_ANNOT_FAEAD_UPD; + return -EAGAIN; } -#endif + /* * Callback to handle sending packets through WRIOP based interface */ @@ -1424,28 +1620,24 @@ uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ - uint32_t loop, retry_count; - int32_t ret; + uint32_t loop, retry_count, i; + int32_t ret, tstamp[MAX_TX_RING_SLOTS]; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; uint32_t frames_to_send; - struct rte_mempool *mp; struct qbman_eq_desc eqdesc; - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; + struct dpaa2_queue *dpaa2_q = queue; struct qbman_swp *swp; uint16_t num_tx = 0; - uint16_t bpid; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct rte_mempool *hw_mp; uint32_t flags[MAX_TX_RING_SLOTS] = {0}; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } @@ -1453,19 +1645,17 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) swp = DPAA2_PER_LCORE_PORTAL; DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); + eth_data, dpaa2_q->fqid); -#ifdef RTE_LIBRTE_IEEE1588 - /* IEEE1588 driver need pointer to tx confirmation queue - * corresponding to last packet transmitted for reading - * the timestamp - */ - if ((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - priv->next_tx_conf_queue = dpaa2_q->tx_conf_queue; - dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue); - priv->tx_timestamp = 0; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + return 0; } -#endif + hw_mp = priv->bp_list->mp; + + if (dpaa2_q->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q, false); /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc); @@ -1473,214 +1663,119 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) qbman_eq_desc_set_fq(&eqdesc, dpaa2_q->fqid); /*Clear the unused FD fields before sending*/ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn(*bufs)) { - uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; - - flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | - dqrr_index; - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); - *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; - } +tx_again: + /*Check if the queue is congested*/ + retry_count = 0; + while (qbman_result_SCN_state(dpaa2_q->cscn)) { + retry_count++; + /* Retry for some time before giving up */ + if (retry_count > CONG_RETRY_COUNT) + goto skip_tx; + } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], mempool_to_bpid(mp)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies - (rte_mempool_from_obj((void *)*bufs), - (void **)bufs, 1, 0); -#endif - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? + dpaa2_eqcr_size : nb_pkts; - if (unlikely(RTE_MBUF_HAS_EXTBUF(*bufs))) { - if (unlikely((*bufs)->nb_segs > 1)) { - mp = (*bufs)->pool; - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - mempool_to_bpid(mp))) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, 0); - } - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } + for (loop = 0; loop < frames_to_send; loop++) { + dy_conf[loop] = false; + if (*dpaa2_seqn(*bufs)) { + uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; + + flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; + DPAA2_PER_LCORE_DQRR_SIZE--; + DPAA2_PER_LCORE_DQRR_HELD &= ~(1 << dqrr_index); + *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; + } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); + if (unlikely((*bufs)->ol_flags + & RTE_MBUF_F_TX_VLAN)) { + ret = rte_vlan_insert(bufs); + if (ret) goto send_n_return; - } + } - if (unlikely((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN)) { - int ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR("S/G support not added" - " for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif + tstamp[loop] = false; + + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { bufs++; + continue; } - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], &flags[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); + } else { + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } + if (ret) + goto send_n_return; + bufs++; + } - num_tx += loop; - nb_pkts -= loop; + loop = 0; + retry_count = 0; + while (loop < frames_to_send) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, + &fd_arr[loop], &flags[loop], + frames_to_send - loop); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { + num_tx += loop; + nb_pkts -= loop; + goto send_n_return; + } + } else { + loop += ret; + retry_count = 0; + } } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); + num_tx += loop; + nb_pkts -= loop; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + for (i = 0; i < loop; i++) { + if (tstamp[i]) + dpaa2_q->tx_conf_queue->ts_to_cnfd++; + } } + if (nb_pkts > 0) + goto tx_again; + + dpaa2_q->tx_pkts += num_tx; return num_tx; send_n_return: /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[i], - &flags[i], - loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } + retry_count = 0; + i = 0; + while (i < loop) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, &fd_arr[i], + &flags[i], loop - i); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + break; + } else { + i += ret; + retry_count = 0; } - num_tx += i; - } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); + num_tx += i; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + loop = i; + for (i = 0; i < loop; i++) { + if (tstamp[i]) + dpaa2_q->tx_conf_queue->ts_to_cnfd++; + } } - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; +skip_tx: dpaa2_q->tx_pkts += num_tx; return num_tx; @@ -1755,149 +1850,110 @@ dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_tx_multi_txq_ordered) uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, - struct rte_mbuf **bufs, uint16_t nb_pkts) + struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to multiple queues respectively.*/ - uint32_t loop, i, retry_count; - int32_t ret; + uint32_t loop, retry_count, sent = 0, i; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS]; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; - struct rte_mempool *mp; + struct rte_mempool *hw_mp; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; struct dpaa2_queue *dpaa2_q[MAX_TX_RING_SLOTS]; struct qbman_swp *swp; - uint16_t bpid; - struct rte_mbuf *mi; struct rte_eth_dev_data *eth_data; struct dpaa2_dev_priv *priv; struct dpaa2_queue *order_sendq; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } } swp = DPAA2_PER_LCORE_PORTAL; +tx_again: frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - dpaa2_q[loop] = (struct dpaa2_queue *)queue[loop]; + dpaa2_q[loop] = queue[loop]; + if (dpaa2_q[loop]->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q[loop], false); eth_data = dpaa2_q[loop]->eth_data; priv = eth_data->dev_private; - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { + dy_conf[loop] = false; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + ret = -ENOMEM; + goto send_frames; + } + hw_mp = priv->bp_list->mp; + if (!priv->en_loose_ordered && + (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP)) { + if (!num_free_eq_desc) { + num_free_eq_desc = dpaa2_free_eq_descriptors(); if (!num_free_eq_desc) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (!num_free_eq_desc) - goto send_frames; + ret = -EIO; + goto send_frames; } - num_free_eq_desc--; } + num_free_eq_desc--; } DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q[loop]->fqid); + eth_data, dpaa2_q[loop]->fqid); /* Check if the queue is congested */ retry_count = 0; while (qbman_result_SCN_state(dpaa2_q[loop]->cscn)) { retry_count++; /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) + if (retry_count > CONG_RETRY_COUNT) { + ret = -ETIME; goto send_frames; + } } /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); if (*dpaa2_seqn(*bufs) && priv->en_ordered) { - order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); + order_sendq = priv->tx_vq[0]; + dpaa2_set_enqueue_descriptor(order_sendq, *bufs, + &eqdesc[loop]); } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q[loop]->fqid); + qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); + qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_frames; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_frames; - } + tstamp[loop] = false; - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; + bufs++; + continue; + } - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_frames; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_frames; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_frames; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } - + if (ret) + goto send_frames; + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; bufs++; } @@ -1918,237 +1974,30 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, break; } } - - for (i = 0; i < free_count; i++) { - if (buf_to_free[i].pkt_id < loop) - rte_pktmbuf_free_seg(buf_to_free[i].seg); + nb_pkts -= loop; + sent += loop; + for (i = 0; i < loop; i++) { + if (tstamp[i] && dpaa2_q[i]->tx_conf_queue) + dpaa2_q[i]->tx_conf_queue->ts_to_cnfd++; } - return loop; + if (nb_pkts > 0 && !ret) + goto tx_again; + + return sent; } /* Callback to handle sending ordered packets through WRIOP based interface */ uint16_t -dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) +dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) { - /* Function to transmit the frames to given device and VQ*/ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_queue *order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; - struct rte_mempool *mp; - struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; - struct qbman_swp *swp; - uint32_t frames_to_send, num_free_eq_desc; - uint32_t loop, retry_count; - int32_t ret; - uint16_t num_tx = 0; - uint16_t bpid; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint16_t i; + void *mq[nb_pkts]; - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); - if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); - return 0; - } - } - swp = DPAA2_PER_LCORE_PORTAL; + for (i = 0; i < nb_pkts; i++) + mq[i] = queue; - DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); - - /* This would also handle normal and atomic queues as any type - * of packet can be enqueued when ordered queues are being used. - */ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (num_free_eq_desc < frames_to_send) - frames_to_send = num_free_eq_desc; - } - } - - for (loop = 0; loop < frames_to_send; loop++) { - /*Prepare enqueue descriptor*/ - qbman_eq_desc_clear(&eqdesc[loop]); - - if (*dpaa2_seqn(*bufs)) { - /* Use only queue 0 for Tx in case of atomic/ - * ordered packets as packets can get unordered - * when being transmitted out from the interface - */ - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); - } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q->fqid); - } - - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_n_return; - } - - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } - bufs++; - } - - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[loop], &fd_arr[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } - } - - num_tx += loop; - nb_pkts -= loop; - } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; - -send_n_return: - /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[i], &fd_arr[i], loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } - } - num_tx += i; - } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; - dpaa2_q->tx_pkts += num_tx; - - return num_tx; + return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); } /* This function loopbacks all the received packets.*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 33/45] net/dpaa2: ptp enhancements 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (31 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 32/45] drivers: rework dpaa2 Tx confirmation Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 34/45] net/dpaa2: remove unused soft parser Tx code Prashant Gupta ` (17 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> 1) Correct TX timestamp only for PTP sync packets. 2) Runtime configure TX timestamp offset by parsing current TX PTP packet format. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 92 ++-------------- drivers/net/dpaa2/dpaa2_ethdev.h | 30 +++++- drivers/net/dpaa2/dpaa2_ptp.c | 176 +++++++++++++++++++++++++------ drivers/net/dpaa2/dpaa2_rxtx.c | 77 +++++++++++++- 4 files changed, 252 insertions(+), 123 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 61b7ae138c..58b4cedee3 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -72,11 +72,6 @@ static uint64_t dev_tx_offloads_sup = static uint64_t dev_tx_offloads_nodis = RTE_ETH_TX_OFFLOAD_MULTI_SEGS; -/* enable timestamp in mbuf */ -bool dpaa2_enable_ts[RTE_MAX_ETHPORTS]; -uint64_t dpaa2_timestamp_rx_dynflag; -int dpaa2_timestamp_dynfield_offset = -1; - bool dpaa2_print_parser_result; /* Rx descriptor limit when DPNI loads PFDRs in PEB */ @@ -730,9 +725,6 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) int tx_l4_csum_offload = false; int ret, tc_index; uint32_t max_rx_pktlen; -#if defined(RTE_LIBRTE_IEEE1588) - uint16_t ptp_correction_offset; -#endif PMD_INIT_FUNC_TRACE(); @@ -814,25 +806,15 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) return ret; } -#if !defined(RTE_LIBRTE_IEEE1588) - if (rx_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) -#endif - { - ret = rte_mbuf_dyn_rx_timestamp_register( - &dpaa2_timestamp_dynfield_offset, - &dpaa2_timestamp_rx_dynflag); - if (ret != 0) { + if (rx_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) { + ret = rte_mbuf_dyn_rx_timestamp_register(&priv->rx_ts_offset, + &priv->rx_ts_flag); + if (ret) { DPAA2_PMD_ERR("Error to register timestamp field/flag"); - return -rte_errno; + return ret; } - dpaa2_enable_ts[dev->data->port_id] = true; } -#if defined(RTE_LIBRTE_IEEE1588) - /* By default setting ptp correction offset for Ethernet SYNC packets */ - ptp_correction_offset = RTE_ETHER_HDR_LEN + 8; - rte_pmd_dpaa2_set_one_step_ts(dev->data->port_id, ptp_correction_offset, 0); -#endif if (tx_offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) tx_l3_csum_offload = true; @@ -3315,8 +3297,6 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, - .mtr_ops_get = dpaa2_mtr_ops_get, -#if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, .timesync_read_time = dpaa2_timesync_read_time, @@ -3324,7 +3304,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .timesync_adjust_time = dpaa2_timesync_adjust_time, .timesync_read_rx_timestamp = dpaa2_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = dpaa2_timesync_read_tx_timestamp, -#endif + .mtr_ops_get = dpaa2_mtr_ops_get, }; /* Populate the mac address from physically available (u-boot/firmware) and/or @@ -3589,11 +3569,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->options = attr.options; priv->max_mac_filters = attr.mac_filter_entries; priv->max_vlan_filters = attr.vlan_filter_entries; - priv->flags = 0; -#if defined(RTE_LIBRTE_IEEE1588) - DPAA2_PMD_INFO("DPDK IEEE1588 is enabled"); - priv->flags |= DPAA2_TX_CONF_ENABLE; -#endif priv->tx_conf_type = DPAA2_TX_NO_CONF; /* Used with ``fslmc:dpni.1,drv_tx_conf=1`` */ @@ -3803,61 +3778,6 @@ rte_pmd_dpaa2_ep_name(uint32_t eth_id) return priv->ep_name; } -#if defined(RTE_LIBRTE_IEEE1588) -RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_get_one_step_ts, 24.11) -int -rte_pmd_dpaa2_get_one_step_ts(uint16_t port_id, bool mc_query) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = priv->eth_dev->process_private; - struct dpni_single_step_cfg ptp_cfg; - int err; - - if (!mc_query) - return priv->ptp_correction_offset; - - err = dpni_get_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &ptp_cfg); - if (err) { - DPAA2_PMD_ERR("Failed to retrieve onestep configuration"); - return err; - } - - if (!ptp_cfg.ptp_onestep_reg_base) { - DPAA2_PMD_ERR("1588 onestep reg not available"); - return -1; - } - - priv->ptp_correction_offset = ptp_cfg.offset; - - return priv->ptp_correction_offset; -} - -RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_set_one_step_ts, 24.11) -int -rte_pmd_dpaa2_set_one_step_ts(uint16_t port_id, uint16_t offset, uint8_t ch_update) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - struct dpni_single_step_cfg cfg; - int err; - - cfg.en = 1; - cfg.ch_update = ch_update; - cfg.offset = offset; - cfg.peer_delay = 0; - - err = dpni_set_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (err) - return err; - - priv->ptp_correction_offset = offset; - - return 0; -} -#endif - static int dpaa2_tx_sg_pool_init(void) { char name[RTE_MEMZONE_NAMESIZE]; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c6a8b4f595..e7490b1e0c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -8,6 +8,7 @@ #ifndef _DPAA2_ETHDEV_H #define _DPAA2_ETHDEV_H +#include <rte_time.h> #include <rte_compat.h> #include <rte_event_eth_rx_adapter.h> #include <rte_pmd_dpaa2.h> @@ -101,6 +102,11 @@ #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) +#define DPAA2_IEEE1588_DEBUG_FLAG RTE_BIT32(13) + +#define DPAA2_IEEE1588_TX_TS_FLAG RTE_BIT32(14) +#define DPAA2_IEEE1588_RX_TS_FLAG RTE_BIT32(15) + /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -507,16 +513,16 @@ struct dpaa2_dev_priv { uint64_t ss_iova; uint64_t ss_param_iova; /*stores timestamp of last received packet on dev*/ - uint64_t rx_timestamp; + RTE_ATOMIC(uint64_t) rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ - uint64_t tx_timestamp; + RTE_ATOMIC(uint64_t) tx_timestamp; int rx_ts_offset; uint64_t rx_ts_flag; /* stores next tx queue to be confirmed that should be processed, * it corresponds to last packet transmitted */ - struct dpaa2_queue *next_txq_to_cnf; + RTE_ATOMIC(struct dpaa2_queue *) next_txq_to_cnf; struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; @@ -591,6 +597,21 @@ dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, } } +static inline void +dpaa2_timestamp_debug(struct dpaa2_dev_priv *priv, + const char *prefix, uint64_t timestamp) +{ + struct timespec ts; + + if (likely(!(priv->flags & DPAA2_IEEE1588_DEBUG_FLAG))) + return; + + ts = rte_ns_to_timespec(timestamp); + DPAA2_PMD_DEBUG("DPAA2 TS DBG: %s: ns(%" PRIu64 ")->%" PRId64 + " seconds/%" PRId64 " nanoseconds", + prefix, timestamp, (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec); +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); @@ -653,6 +674,9 @@ void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); uint16_t dpaa2_dev_tx_conf(void *txq, int drain); +void +dpaa2_dev_tx_ptp_one_step_runtime(struct rte_eth_dev *dev, + struct rte_mbuf *buf, int *tstamp, int *set); int dpaa2_timesync_enable(struct rte_eth_dev *dev); int dpaa2_timesync_disable(struct rte_eth_dev *dev); int dpaa2_timesync_read_time(struct rte_eth_dev *dev, diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index c845291c68..71b811aff6 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2019, 2023 NXP + * Copyright 2019, 2023-2026 NXP */ #include <sys/queue.h> @@ -22,6 +22,7 @@ #include <dpaa2_ethdev.h> #include <dpaa2_pmd_logs.h> +#include <dpaax_ptp.h> struct dpaa2_dprtc_dev { struct fsl_mc_io dprtc; /** handle to DPRTC portal object */ @@ -30,52 +31,144 @@ struct dpaa2_dprtc_dev { }; static struct dpaa2_dprtc_dev *dprtc_dev; -int dpaa2_timesync_enable(struct rte_eth_dev *dev __rte_unused) +static int +dpaa2_timesync_set_one_step(struct rte_eth_dev *dev, + uint16_t offset, int udp) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = dev->process_private; + struct dpni_single_step_cfg cfg; + int err; + + memset(&cfg, 0, sizeof(struct dpni_single_step_cfg)); + cfg.en = 1; + cfg.ch_update = udp; + cfg.offset = offset; + cfg.peer_delay = 0; + + err = dpni_set_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg); + if (err) + return err; + + priv->ptp_correction_offset = offset; + + return 0; +} + +void +dpaa2_dev_tx_ptp_one_step_runtime(struct rte_eth_dev *dev, + struct rte_mbuf *buf, int *tstamp, int *set) { + uint16_t ts_offset; + int is_udp = false, ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (tstamp) + *tstamp = false; + if (set) + *set = false; + + if (!dpaax_timesync_ptp_parse_header(buf, + &ts_offset, &is_udp)) { + DPAA2_PMD_WARN("Tx packet is not PTP frame."); + ret = -EINVAL; + } else { + if (ts_offset != priv->ptp_correction_offset) { + ret = dpaa2_timesync_set_one_step(dev, ts_offset, is_udp); + if (ret) { + DPAA2_PMD_WARN("Change one step failed(%d)", ret); + } else { + DPAA2_PMD_INFO("Change one step from offset %d to %d", + priv->ptp_correction_offset, ts_offset); + priv->ptp_correction_offset = ts_offset; + if (set) + *set = true; + } + } + } + + if (!ret && tstamp) + *tstamp = true; +} + +int dpaa2_timesync_enable(struct rte_eth_dev *dev) +{ + uint16_t default_offset; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret; + + default_offset = RTE_ETHER_HDR_LEN + + offsetof(struct rte_dpaax_ptp_header, correction); + + ret = dpaa2_timesync_set_one_step(dev, default_offset, false); + if (ret) { + DPAA2_PMD_ERR("%s one step timesyc set failed(%d)", + dev->data->name, ret); + } else { + priv->flags |= DPAA2_IEEE1588_TX_TS_FLAG; + } + priv->flags |= DPAA2_IEEE1588_RX_TS_FLAG; + if (priv->tx_conf_type == DPAA2_TX_NO_CONF) { + DPAA2_PMD_WARN("%s Unable to read TX timestamp", + dev->data->name); + } + if (getenv("DPAA2_IEEE1588_DEBUG_ENABLE")) + priv->flags |= DPAA2_IEEE1588_DEBUG_FLAG; + return 0; } -int dpaa2_timesync_disable(struct rte_eth_dev *dev __rte_unused) +int dpaa2_timesync_disable(struct rte_eth_dev *dev) { + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + priv->ptp_correction_offset = 0; + priv->flags &= ~DPAA2_IEEE1588_RX_TS_FLAG; + priv->flags &= ~DPAA2_IEEE1588_TX_TS_FLAG; return 0; } int dpaa2_timesync_read_time(struct rte_eth_dev *dev, - struct timespec *timestamp) + struct timespec *timestamp) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ret = dprtc_get_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &ns); + dprtc_dev->token, &ns); if (ret) { DPAA2_PMD_ERR("dprtc_get_time failed ret: %d", ret); return ret; } *timestamp = rte_ns_to_timespec(ns); + dpaa2_timestamp_debug(priv, __func__, ns); return 0; } int dpaa2_timesync_write_time(struct rte_eth_dev *dev, - const struct timespec *ts) + const struct timespec *ts) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ns = rte_timespec_to_ns(ts); - ret = dprtc_set_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, ns); + dprtc_dev->token, ns); if (ret) { DPAA2_PMD_ERR("dprtc_set_time failed ret: %d", ret); return ret; } + dpaa2_timestamp_debug(priv, __func__, ns); return 0; } @@ -84,11 +177,13 @@ int dpaa2_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ret = dprtc_get_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &ns); + dprtc_dev->token, &ns); if (ret) { DPAA2_PMD_ERR("dprtc_get_time failed ret: %d", ret); return ret; @@ -102,64 +197,84 @@ int dpaa2_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) DPAA2_PMD_ERR("dprtc_set_time failed ret: %d", ret); return ret; } + dpaa2_timestamp_debug(priv, "adjust delata", delta); + dpaa2_timestamp_debug(priv, "adjust absolute", ns); return 0; } int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, - struct timespec *timestamp) + struct timespec *timestamp) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - - if (priv->next_txq_to_cnf) { - while (!priv->tx_timestamp) - dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); - } else { - return -1; + struct dpaa2_queue *txq; + uint64_t ts; + + if (!(priv->flags & DPAA2_IEEE1588_TX_TS_FLAG) || + priv->tx_conf_type == DPAA2_TX_NO_CONF) + return -EINVAL; + + txq = rte_atomic_load_explicit(&priv->next_txq_to_cnf, + rte_memory_order_relaxed); + while (txq && txq->ts_to_cnfd > 0) { + dpaa2_dev_tx_conf(txq, false); + txq = rte_atomic_load_explicit(&priv->next_txq_to_cnf, + rte_memory_order_relaxed); } - *timestamp = rte_ns_to_timespec(priv->tx_timestamp); + + ts = rte_atomic_load_explicit(&priv->tx_timestamp, + rte_memory_order_relaxed); + *timestamp = rte_ns_to_timespec(ts); + dpaa2_timestamp_debug(priv, __func__, ts); return 0; } int dpaa2_timesync_read_rx_timestamp(struct rte_eth_dev *dev, - struct timespec *timestamp, - uint32_t flags __rte_unused) + struct timespec *timestamp, uint32_t flags __rte_unused) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - *timestamp = rte_ns_to_timespec(priv->rx_timestamp); + uint64_t ts; + + if (!(priv->flags & DPAA2_IEEE1588_RX_TS_FLAG)) + return -EINVAL; + + ts = rte_atomic_load_explicit(&priv->rx_timestamp, + rte_memory_order_relaxed); + *timestamp = rte_ns_to_timespec(ts); + dpaa2_timestamp_debug(priv, __func__, ts); + return 0; } -#if defined(RTE_LIBRTE_IEEE1588) static int dpaa2_create_dprtc_device(int vdev_fd __rte_unused, struct vfio_device_info *obj_info __rte_unused, struct rte_dpaa2_device *obj) { struct dprtc_attr attr; - int ret, dprtc_id = obj->object_id; + int ret = 0, dprtc_id = obj->object_id; PMD_INIT_FUNC_TRACE(); /* Allocate DPAA2 dprtc handle */ - dprtc_dev = rte_malloc(NULL, sizeof(struct dpaa2_dprtc_dev), 0); + dprtc_dev = rte_zmalloc(NULL, sizeof(struct dpaa2_dprtc_dev), 0); if (!dprtc_dev) { DPAA2_PMD_ERR("Memory allocation failed for DPRTC Device"); - return -1; + return -ENOMEM; } /* Open the dprtc object */ dprtc_dev->dprtc.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); ret = dprtc_open(&dprtc_dev->dprtc, CMD_PRI_LOW, dprtc_id, - &dprtc_dev->token); + &dprtc_dev->token); if (ret) { DPAA2_PMD_ERR("Unable to open dprtc object: err(%d)", ret); goto init_err; } ret = dprtc_get_attributes(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &attr); + dprtc_dev->token, &attr); if (ret) { DPAA2_PMD_ERR("Unable to get dprtc attr: err(%d)", ret); goto init_err; @@ -172,7 +287,7 @@ dpaa2_create_dprtc_device(int vdev_fd __rte_unused, init_err: rte_free(dprtc_dev); - return -1; + return ret; } static struct rte_dpaa2_object rte_dpaa2_dprtc_obj = { @@ -181,4 +296,3 @@ static struct rte_dpaa2_object rte_dpaa2_dprtc_obj = { }; RTE_PMD_REGISTER_DPAA2_OBJECT(dprtc, rte_dpaa2_dprtc_obj); -#endif diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 4512c8cf00..eda88a7bed 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -22,6 +22,7 @@ #include <dpaa2_hw_pvt.h> #include <dpaa2_hw_dpio.h> #include <dpaa2_hw_mempool.h> +#include <dpaax_ptp.h> #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" @@ -115,6 +116,30 @@ dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, m->hash.rss); } } + +static inline void +dpaa2_dev_rx_read_timestamp(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m) +{ + struct dpaa2_annot_hdr *annotation; + rte_mbuf_timestamp_t *ts; + + if (!(priv->flags & DPAA2_IEEE1588_RX_TS_FLAG)) + return; + + annotation = (void *)((uint8_t *)m->buf_addr + DPAA2_FD_PTA_SIZE); + if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) { + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST; + } + ts = RTE_MBUF_DYNFIELD(m, priv->rx_ts_offset, void *); + *ts = annotation->word2; + m->ol_flags |= priv->rx_ts_flag; + rte_atomic_store_explicit(&priv->rx_timestamp, *ts, + rte_memory_order_relaxed); + dpaa2_timestamp_debug(priv, __func__, priv->rx_timestamp); +} + static void __rte_hot dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, struct rte_mbuf *m, const struct qbman_fd *fd, @@ -956,6 +981,8 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, mbuf, fd); + dpaa2_dev_rx_read_timestamp(priv, mbuf); + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -1131,6 +1158,8 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); + dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1381,6 +1410,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); + dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1424,6 +1454,8 @@ dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, return true; } +#define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + uint16_t dpaa2_dev_tx_conf(void *txq, int drain) { /* Function receive frames for a given device and VQ*/ @@ -1441,7 +1473,10 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) struct rte_mbuf *mbufs[dpaa2_dqrr_size]; struct rte_mempool *mp = NULL; - #define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct dpaa2_annot_hdr *annotation; + void *v_addr; conf_again: bulk_free = true; @@ -1539,6 +1574,16 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) if (bulk_free && !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) bulk_free = false; + if (unlikely(mbufs[idx]->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)) { + v_addr = mbufs[idx]->buf_addr; + annotation = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); + rte_atomic_store_explicit(&priv->tx_timestamp, + annotation->word2, rte_memory_order_relaxed); + rte_atomic_store_explicit(&priv->next_txq_to_cnf, + dpaa2_txq, rte_memory_order_relaxed); + dpaa2_q->ts_to_cnfd--; + dpaa2_timestamp_debug(priv, __func__, priv->tx_timestamp); + } idx++; dq_storage++; if (idx >= dpaa2_dqrr_size) @@ -1621,7 +1666,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ uint32_t loop, retry_count, i; - int32_t ret, tstamp[MAX_TX_RING_SLOTS]; + int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send; struct qbman_eq_desc eqdesc; @@ -1667,6 +1712,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) tx_again: /*Check if the queue is congested*/ retry_count = 0; + ptp_set_count = 0; while (qbman_result_SCN_state(dpaa2_q->cscn)) { retry_count++; /* Retry for some time before giving up */ @@ -1696,6 +1742,17 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } tstamp[loop] = false; + if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && + (priv->flags & DPAA2_IEEE1588_TX_TS_FLAG))) { + ptp_set = false; + dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, + &tstamp[loop], &ptp_set); + if (ptp_set) + ptp_set_count++; + if (ptp_set_count > 1) + DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); + goto skip_fast_mbuf2fd; + } ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, *bufs, &fd_arr[loop], priv->tx_conf_type); @@ -1704,6 +1761,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) continue; } +skip_fast_mbuf2fd: if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); @@ -1854,7 +1912,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, { /* Function to transmit the frames to multiple queues respectively.*/ uint32_t loop, retry_count, sent = 0, i; - int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS]; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; struct rte_mempool *hw_mp; @@ -1877,6 +1935,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, swp = DPAA2_PER_LCORE_PORTAL; tx_again: + ptp_set_count = 0; frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; @@ -1933,6 +1992,17 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, } tstamp[loop] = false; + if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && + (priv->flags & DPAA2_IEEE1588_TX_TS_FLAG))) { + ptp_set = false; + dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, + &tstamp[loop], &ptp_set); + if (ptp_set) + ptp_set_count++; + if (ptp_set_count > 1) + DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); + goto skip_fast_mbuf2fd; + } ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, *bufs, &fd_arr[loop], priv->tx_conf_type); @@ -1943,6 +2013,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, continue; } +skip_fast_mbuf2fd: if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 34/45] net/dpaa2: remove unused soft parser Tx code 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (32 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 33/45] net/dpaa2: ptp enhancements Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 35/45] net/dpaa2: update MC dpni QoS and flow steering API Prashant Gupta ` (16 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Remove the soft parser related code from the Tx path. The soft parser can only be loaded before Linux boots, so this code was never reachable at runtime. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_rxtx.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index eda88a7bed..5c6a77d2f8 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -169,16 +169,6 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; } } - if (priv->sp_protocol) { - if (frc_parse->fafe2) { - frc_parse->fafe2 = 0; - ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; - } - if (frc_parse->sum_l.l4.fafe3) { - frc_parse->sum_l.l4.fafe3 = 0; - ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; - } - } switch (frc) { case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 35/45] net/dpaa2: update MC dpni QoS and flow steering API 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (33 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 34/45] net/dpaa2: remove unused soft parser Tx code Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 36/45] net/dpaa2: enhance xstat implementation Prashant Gupta ` (15 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Update the MC firmware command interface for the QoS and flow steering (FS) tables ahead of the flow engine rework: - Version the SET_QOS_TBL / ADD_FS_ENT commands and add dpni_set_qos_table_v2() and dpni_add_fs_entry_legacy() wrappers. - Support a per-entry default flow id in the QoS table configuration. - Replace the single redirect_obj_token in dpni_fs_action_cfg with a redir_tokens[] array plus num_tokens, and program it via the new ADD_FS_ENT command. - Add the dpni dump-table structures. The existing flow code is updated to populate the new redir_tokens[] field so behaviour is unchanged. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 3 +- drivers/net/dpaa2/mc/dpni.c | 127 ++++++++++++++++++++-------- drivers/net/dpaa2/mc/fsl_dpni.h | 100 ++++++++++++++++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 30 ++++--- 4 files changed, 206 insertions(+), 54 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index cde2f5a9d3..c616857e98 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4444,7 +4444,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, dest_q = dest_priv->tx_vq[0]; flow->fs_action_cfg.options = DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; - flow->fs_action_cfg.redirect_obj_token = + flow->fs_action_cfg.num_tokens = 1; + flow->fs_action_cfg.redir_tokens[0] = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index 17275b7195..8e4114e604 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #include <fsl_mc_sys.h> @@ -1937,32 +1937,43 @@ int dpni_get_queue_tx_confirmation_mode(struct fsl_mc_io *mc_io, * * Return: '0' on Success; Error code otherwise. */ -int dpni_set_qos_table(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_qos_tbl_cfg *cfg) +static int +_dpni_set_qos_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg, uint16_t cmd_id) { struct dpni_cmd_set_qos_table *cmd_params; struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL, - cmd_flags, - token); - cmd_params = (struct dpni_cmd_set_qos_table *)cmd.params; + cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, token); + cmd_params = (void *)cmd.params; cmd_params->default_tc = cfg->default_tc; cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova); - dpni_set_field(cmd_params->discard_on_miss, - ENABLE, - cfg->discard_on_miss); - dpni_set_field(cmd_params->discard_on_miss, - KEEP_QOS_ENTRIES, - cfg->keep_entries); + if (DPNI_CMD_VER(cmd_id) > DPNI_CMD_VERSION_2) + cmd_params->default_flow_id = cpu_to_le16(cfg->default_flow_id); + dpni_set_field(cmd_params->flags, DISCARD_ON_MISS, cfg->discard_on_miss); + dpni_set_field(cmd_params->flags, KEEP_QOS_ENTRIES, cfg->keep_entries); + if (DPNI_CMD_VER(cmd_id) > DPNI_CMD_VERSION_2) + dpni_set_field(cmd_params->flags, SET_DEFAULT_FLOW_ID, cfg->set_default_flow_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +int +dpni_set_qos_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg) +{ + return _dpni_set_qos_table(mc_io, cmd_flags, token, cfg, DPNI_CMDID_SET_QOS_TBL); +} + +int +dpni_set_qos_table_v2(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg) +{ + return _dpni_set_qos_table(mc_io, cmd_flags, token, cfg, DPNI_CMDID_SET_QOS_TBL_V2); +} + /** * dpni_add_qos_entry() - Add QoS mapping entry (to select a traffic class) * @mc_io: Pointer to MC portal's I/O object @@ -2086,6 +2097,7 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, { struct dpni_cmd_add_fs_entry *cmd_params; struct mc_command cmd = { 0 }; + int i; /* prepare command */ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT, @@ -2100,7 +2112,36 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, cmd_params->options = cpu_to_le16(action->options); cmd_params->flow_id = cpu_to_le16(action->flow_id); cmd_params->flc = cpu_to_le64(action->flc); - cmd_params->redir_token = cpu_to_le16(action->redirect_obj_token); + cmd_params->token_num = action->num_tokens; + for (i = 0; i < DPNI_FS_REDIR_MAX_NUM; i++) + cmd_params->redir_tokens[i] = cpu_to_le16(action->redir_tokens[i]); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_add_fs_entry_legacy(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, + uint8_t tc_id, uint16_t index, + const struct dpni_rule_cfg *cfg, + const struct dpni_fs_action_cfg *action) +{ + struct dpni_cmd_add_fs_entry *cmd_params; + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT_LEGACY, + cmd_flags, token); + cmd_params = (struct dpni_cmd_add_fs_entry *)cmd.params; + cmd_params->tc_id = tc_id; + cmd_params->key_size = cfg->key_size; + cmd_params->index = cpu_to_le16(index); + cmd_params->key_iova = cpu_to_le64(cfg->key_iova); + cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova); + cmd_params->options = cpu_to_le16(action->options); + cmd_params->flow_id = cpu_to_le16(action->flow_id); + cmd_params->flc = cpu_to_le64(action->flc); + cmd_params->redir_tokens[0] = cpu_to_le16(action->redir_tokens[0]); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -2169,30 +2210,16 @@ int dpni_clear_fs_entries(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } -/** - * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @tc_id: Traffic class selection (0-7) - * @cfg: Traffic class policing configuration - * - * Return: '0' on Success; error code otherwise. - */ -int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t tc_id, - const struct dpni_rx_tc_policing_cfg *cfg) +static int +_dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg, uint16_t cmd_id) { struct dpni_cmd_set_rx_tc_policing *cmd_params; struct mc_command cmd = { 0 }; - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_POLICING, - cmd_flags, - token); - cmd_params = (struct dpni_cmd_set_rx_tc_policing *)cmd.params; + cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, token); + cmd_params = (void *)cmd.params; dpni_set_field(cmd_params->mode_color, COLOR, cfg->default_color); dpni_set_field(cmd_params->mode_color, MODE, cfg->mode); dpni_set_field(cmd_params->units, UNITS, cfg->units); @@ -2207,6 +2234,34 @@ int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @tc_id: Traffic class selection (0-7) + * @cfg: Traffic class policing configuration + * + * Return: '0' on Success; error code otherwise. + */ +int +dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg) +{ + return _dpni_set_rx_tc_policing(mc_io, cmd_flags, token, tc_id, cfg, + DPNI_CMDID_SET_RX_TC_POLICING); +} + +int +dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg) +{ + return _dpni_set_rx_tc_policing(mc_io, cmd_flags, token, tc_id, cfg, + DPNI_CMDID_SET_RX_TC_POLICING_V1); +} + /** * dpni_get_rx_tc_policing() - Get Rx traffic class policing configuration * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index d227025e01..f315bb7004 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #ifndef __FSL_DPNI_H @@ -121,6 +121,9 @@ struct fsl_mc_io; * The stashing is enabled by default. */ #define DPNI_OPT_STASHING_DIS 0x002000 + +#define DPNI_OPT_V8_HAS_REPLICATION 0x00004000 + /* * PFDR in PEB mode (v1 layout). * The total number of Rx descriptors is limited to 11264 in this mode. @@ -1554,6 +1557,8 @@ struct dpni_qos_tbl_cfg { int discard_on_miss; int keep_entries; uint8_t default_tc; + int set_default_flow_id; + uint16_t default_flow_id; }; int dpni_set_qos_table(struct fsl_mc_io *mc_io, @@ -1561,6 +1566,11 @@ int dpni_set_qos_table(struct fsl_mc_io *mc_io, uint16_t token, const struct dpni_qos_tbl_cfg *cfg); +int dpni_set_qos_table_v2(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + const struct dpni_qos_tbl_cfg *cfg); + /** * struct dpni_rule_cfg - Rule configuration for table lookup * @key_iova: I/O virtual address of the key (must be in DMA-able memory) @@ -1573,6 +1583,10 @@ struct dpni_rule_cfg { uint8_t key_size; }; +#define DPNI_QOS_OPT_SET_TC_ONLY 0x0 +#define DPNI_QOS_OPT_SET_FLOW_ID 0x1 +#define DPNI_QOS_OPT_UPDATE_IF_EXISTS 0x2 + int dpni_add_qos_entry(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, @@ -1633,6 +1647,22 @@ int dpni_clear_qos_table(struct fsl_mc_io *mc_io, */ #define DPNI_FS_OPT_REDIRECT_TO_DPNI_TX 0x10 +/** + * Redirect matching traffic into multiple Tx queues of other dpni objects. + * The frame will be transmitted directly + */ +#define DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX 0x20 + +/** + * In case the FS rule already exists (key and mask), update its action. + * Cannot be used with the actions which redirect the frame towards other DPNIs. + */ +#define DPNI_FS_OPT_UPDATE_IF_EXISTS 0x40 + +#ifndef DPNI_FS_REDIR_MAX_NUM +#define DPNI_FS_REDIR_MAX_NUM 8 +#endif + /** * struct dpni_fs_action_cfg - Action configuration for table look-up * @flc: FLC value for traffic matching this rule. Please check the Frame @@ -1650,12 +1680,38 @@ int dpni_clear_qos_table(struct fsl_mc_io *mc_io, * - if DPNI_FS_OPT_DISCARD is cleared the frame will be enqueued in queue with * index provided in flow_id parameter. * @options: Any combination of DPNI_FS_OPT_ values. + * @token_num: Number of tokens supplied. For DPNI_FS_OPT_REDIRECT_TO_DPNI_RX + * or DPNI_FS_OPT_REDIRECT_TO_DPNI_TX, the token_num must be 1 since there is + * only one token which is necessary. Accepted values are in the + * [1-8] range in case a REDIRECT option is requested. + * @redir_tokens: Array of tokens that identify the object where frame is redirected + * when this rule is hit. This parameter is used only when one + * of the flags DPNI_FS_OPT_REDIRECT_TO_DPNI_RX, + * DPNI_FS_OPT_REDIRECT_TO_DPNI_TX or + * DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX is set. The tokens + * are obtained using dpni_open() API call. The objects must + * stay open during the operation to ensure the fact that + * application has access on them. + * If the object is destroyed of closed, the following actions + * will take place: + * - In case of DPNI_FS_OPT_REDIRECT_TO_DPNI_TX and + * DPNI_FS_OPT_REDIRECT_TO_DPNI_RX: + * + if DPNI_FS_OPT_DISCARD is set the frame will be + * discarded by current dpni + * + if DPNI_FS_OPT_DISCARD is cleared the frame will be + * enqueued in queue with index provided in flow_id + * parameter. + * - In case of DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX, the + * frame will be redirected to the remaining opened target + * DPNIs. If there are no more opened target DPNIs, the frame + * will be discarded. */ struct dpni_fs_action_cfg { uint64_t flc; uint16_t flow_id; - uint16_t redirect_obj_token; uint16_t options; + uint16_t num_tokens; + uint16_t redir_tokens[DPNI_FS_REDIR_MAX_NUM]; }; int dpni_add_fs_entry(struct fsl_mc_io *mc_io, @@ -1666,6 +1722,14 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, const struct dpni_rule_cfg *cfg, const struct dpni_fs_action_cfg *action); +int dpni_add_fs_entry_legacy(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + uint16_t index, + const struct dpni_rule_cfg *cfg, + const struct dpni_fs_action_cfg *action); + int dpni_remove_fs_entry(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, @@ -1928,7 +1992,7 @@ void dpni_extract_sw_sequence_layout(struct dpni_sw_sequence_layout *layout, * When used for queue_idx in function dpni_set_rx_dist_default_queue will signal to dpni * to drop all unclassified frames */ -#define DPNI_FS_MISS_DROP ((uint16_t)-1) +#define DPNI_FS_MISS_ACTION_DROP ((uint16_t)-1) /** * struct dpni_rx_dist_cfg - distribution configuration @@ -1941,9 +2005,10 @@ void dpni_extract_sw_sequence_layout(struct dpni_sw_sequence_layout *layout, * @enable: enable/disable the distribution. * @tc: TC id for which distribution is set * @fs_miss_flow_id: when packet misses all rules from flow steering table and hash is - * disabled it will be put into this queue id; use DPNI_FS_MISS_DROP to drop - * frames. The value of this field is used only when flow steering distribution - * is enabled and hash distribution is disabled + * disabled it will be put into this queue id; + * use DPNI_FS_MISS_ACTION_DROP to drop frames. + * The value of this field is used only when flow steering + * distribution is enabled and hash distribution is disabled. */ struct dpni_rx_dist_cfg { uint16_t dist_size; @@ -2035,6 +2100,29 @@ enum dpni_table_type { DPNI_VLAN_TABLE = 4, }; +struct __rte_packed_begin dpni_dump_table_header { + uint16_t table_type; + uint16_t table_num_entries; + uint16_t table_max_entries; + uint8_t default_action; + uint8_t match_type; + uint8_t reserved[24]; +} __rte_packed_end; + +struct __rte_packed_begin dpni_dump_table_entry { + uint8_t key[DPNI_MAX_KEY_SIZE]; + uint8_t mask[DPNI_MAX_KEY_SIZE]; + uint8_t key_action; + uint16_t result[3]; + uint16_t rule_index; + uint8_t reserved[19]; +} __rte_packed_end; + +struct __rte_packed_begin dpni_dump_table_rsp { + struct dpni_dump_table_header hdr; + struct dpni_dump_table_entry entry[]; +} __rte_packed_end; + int dpni_dump_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index 6b396ca7cc..36e4aacc3a 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #ifndef _FSL_DPNI_CMD_H @@ -20,6 +20,7 @@ #define DPNI_CMD_VERSION_7 7 #define DPNI_CMD_ID_OFFSET 4 +#define DPNI_CMD_VER(cmd_id) ((cmd_id) & ((1 << DPNI_CMD_ID_OFFSET) - 1)) #define DPNI_CMD(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_BASE_VERSION) #define DPNI_CMD_V2(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_VERSION_2) #define DPNI_CMD_V3(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_VERSION_3) @@ -77,13 +78,16 @@ #define DPNI_CMDID_SET_RX_TC_DIST DPNI_CMD_V4(0x235) -#define DPNI_CMDID_SET_RX_TC_POLICING DPNI_CMD(0x23E) +#define DPNI_CMDID_SET_RX_TC_POLICING_V1 DPNI_CMD(0x23E) +#define DPNI_CMDID_SET_RX_TC_POLICING DPNI_CMD_V2(0x23E) -#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD_V2(0x240) +#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD_V3(0x240) +#define DPNI_CMDID_SET_QOS_TBL_V2 DPNI_CMD_V2(0x240) #define DPNI_CMDID_ADD_QOS_ENT DPNI_CMD_V2(0x241) #define DPNI_CMDID_REMOVE_QOS_ENT DPNI_CMD(0x242) #define DPNI_CMDID_CLR_QOS_TBL DPNI_CMD(0x243) -#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD_V2(0x244) +#define DPNI_CMDID_ADD_FS_ENT_LEGACY DPNI_CMD_V2(0x244) +#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD_V3(0x244) #define DPNI_CMDID_REMOVE_FS_ENT DPNI_CMD(0x245) #define DPNI_CMDID_CLR_FS_ENT DPNI_CMD(0x246) @@ -584,19 +588,18 @@ struct dpni_cmd_set_queue { #define DPNI_DISCARD_ON_MISS_SIZE 1 #define DPNI_KEEP_QOS_ENTRIES_SHIFT 1 #define DPNI_KEEP_QOS_ENTRIES_SIZE 1 +#define DPNI_SET_DEFAULT_FLOW_ID_SHIFT 2 +#define DPNI_SET_DEFAULT_FLOW_ID_SIZE 1 struct dpni_cmd_set_qos_table { - uint32_t pad; + uint16_t pad; + uint16_t default_flow_id; uint8_t default_tc; - /* only the LSB */ - uint8_t discard_on_miss; + uint8_t flags; uint16_t pad1[21]; uint64_t key_cfg_iova; }; -#define DPNI_QOS_OPT_SET_TC_ONLY 0x0 -#define DPNI_QOS_OPT_SET_FLOW_ID 0x1 - struct dpni_cmd_add_qos_entry { uint8_t flags; uint8_t flow_id; @@ -616,6 +619,10 @@ struct dpni_cmd_remove_qos_entry { uint64_t mask_iova; }; +#ifndef DPNI_FS_REDIR_MAX_NUM +#define DPNI_FS_REDIR_MAX_NUM 8 +#endif + struct dpni_cmd_add_fs_entry { uint16_t options; uint8_t tc_id; @@ -625,7 +632,8 @@ struct dpni_cmd_add_fs_entry { uint64_t key_iova; uint64_t mask_iova; uint64_t flc; - uint16_t redir_token; + uint16_t redir_tokens[DPNI_FS_REDIR_MAX_NUM]; + uint8_t token_num; }; struct dpni_cmd_remove_fs_entry { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 36/45] net/dpaa2: enhance xstat implementation 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (34 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 35/45] net/dpaa2: update MC dpni QoS and flow steering API Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 37/45] net/dpaa2: rework flow engine Prashant Gupta ` (14 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> 1) Adapt RTE xstat API to return proper length. 2) Alloc DMA buffer of mac xstat only once. 3) Get MAC counter via dpni only when this dpni is connected to DPMAC. 4) Get TC policer counter only when meter flow of TC is there. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 930 ++++++++++++++++++------------- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +- drivers/net/dpaa2/mc/fsl_dpni.h | 259 +++++++-- 3 files changed, 756 insertions(+), 445 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 58b4cedee3..1836226706 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -26,6 +26,7 @@ #include <dpaa2_hw_pvt.h> #include <dpaa2_hw_mempool.h> #include <dpaa2_hw_dpio.h> +#include <fsl_dprc.h> #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" @@ -108,116 +109,287 @@ dpaa2_dist_size_is_supported(uint16_t n) int dpaa2_valid_dev; struct rte_mempool *dpaa2_tx_sg_pool; -struct rte_dpaa2_xstats_name_off { - char name[RTE_ETH_XSTATS_NAME_SIZE]; - uint8_t page_id; /* dpni statistics page id */ - uint8_t stats_id; /* stats id in the given page */ +struct dpaa2_xstats_seq { + struct dpni_statistics_page_0 pg0; + struct dpni_statistics_page_1 pg1; + struct dpni_statistics_page_2 pg2; + struct dpni_statistics_page_3 pg3; + struct dpni_statistics_page_4 pg4; + struct dpni_statistics_page_5 pg5[MAX_TCS]; + struct dpni_statistics_page_6 pg6; + struct dpni_dpmac_counters mac_cnt; }; -static const struct rte_dpaa2_xstats_name_off dpaa2_xstats_strings[] = { - {"ingress_multicast_frames", 0, 2}, - {"ingress_multicast_bytes", 0, 3}, - {"ingress_broadcast_frames", 0, 4}, - {"ingress_broadcast_bytes", 0, 5}, - {"egress_multicast_frames", 1, 2}, - {"egress_multicast_bytes", 1, 3}, - {"egress_broadcast_frames", 1, 4}, - {"egress_broadcast_bytes", 1, 5}, - {"ingress_filtered_frames", 2, 0}, - {"ingress_discarded_frames", 2, 1}, - {"ingress_nobuffer_discards", 2, 2}, - {"egress_discarded_frames", 2, 3}, - {"egress_confirmed_frames", 2, 4}, - {"cgr_reject_frames", 4, 0}, - {"cgr_reject_bytes", 4, 1}, - {"TC_0_policer_cnt_red", 5, 0}, - {"TC_0_policer_cnt_yellow", 5, 1}, - {"TC_0_policer_cnt_green", 5, 2}, - {"TC_0_policer_cnt_re_red", 5, 3}, - {"TC_0_policer_cnt_re_yellow", 5, 4}, - {"TC_1_policer_cnt_red", 6, 0}, - {"TC_1_policer_cnt_yellow", 6, 1}, - {"TC_1_policer_cnt_green", 6, 2}, - {"TC_1_policer_cnt_re_red", 6, 3}, - {"TC_1_policer_cnt_re_yellow", 6, 4}, - {"TC_2_policer_cnt_red", 7, 0}, - {"TC_2_policer_cnt_yellow", 7, 1}, - {"TC_2_policer_cnt_green", 7, 2}, - {"TC_2_policer_cnt_re_red", 7, 3}, - {"TC_2_policer_cnt_re_yellow", 7, 4}, - {"TC_3_policer_cnt_red", 8, 0}, - {"TC_3_policer_cnt_yellow", 8, 1}, - {"TC_3_policer_cnt_green", 8, 2}, - {"TC_3_policer_cnt_re_red", 8, 3}, - {"TC_3_policer_cnt_re_yellow", 8, 4}, - {"TC_4_policer_cnt_red", 9, 0}, - {"TC_4_policer_cnt_yellow", 9, 1}, - {"TC_4_policer_cnt_green", 9, 2}, - {"TC_4_policer_cnt_re_red", 9, 3}, - {"TC_4_policer_cnt_re_yellow", 9, 4}, - {"TC_5_policer_cnt_red", 10, 0}, - {"TC_5_policer_cnt_yellow", 10, 1}, - {"TC_5_policer_cnt_green", 10, 2}, - {"TC_5_policer_cnt_re_red", 10, 3}, - {"TC_5_policer_cnt_re_yellow", 10, 4}, - {"TC_6_policer_cnt_red", 11, 0}, - {"TC_6_policer_cnt_yellow", 11, 1}, - {"TC_6_policer_cnt_green", 11, 2}, - {"TC_6_policer_cnt_re_red", 11, 3}, - {"TC_6_policer_cnt_re_yellow", 11, 4}, - {"TC_7_policer_cnt_red", 12, 0}, - {"TC_7_policer_cnt_yellow", 12, 1}, - {"TC_7_policer_cnt_green", 12, 2}, - {"TC_7_policer_cnt_re_red", 12, 3}, - {"TC_7_policer_cnt_re_yellow", 12, 4}, - {"mac_rx_64 bytes", 0, 0}, - {"mac_rx_65-127 bytes", 0, 0}, - {"mac_rx_128-255 bytes", 0, 0}, - {"mac_rx_256-511 bytes", 0, 0}, - {"mac_rx_512-1023 bytes", 0, 0}, - {"mac_rx_1024-1518 bytes", 0, 0}, - {"mac_rx_1519-max bytes", 0, 0}, - {"mac_rx_frags", 0, 0}, - {"mac_rx_jabber", 0, 0}, - {"mac_rx_frame discards", 0, 0}, - {"mac_rx_align errors", 0, 0}, - {"mac_tx_undersized", 0, 0}, - {"mac_rx_oversized", 0, 0}, - {"mac_rx_pause", 0, 0}, - {"mac_tx_b-pause", 0, 0}, - {"mac_rx_bytes", 0, 0}, - {"mac_rx_m-cast", 0, 0}, - {"mac_rx_b-cast", 0, 0}, - {"mac_rx_all frames", 0, 0}, - {"mac_rx_u-cast", 0, 0}, - {"mac_rx_frame errors", 0, 0}, - {"mac_tx_bytes", 0, 0}, - {"mac_tx_m-cast", 0, 0}, - {"mac_tx_b-cast", 0, 0}, - {"mac_tx_u-cast", 0, 0}, - {"mac_tx_frame errors", 0, 0}, - {"mac_rx_frames ok", 0, 0}, - {"mac_tx_frames ok", 0, 0}, - {"mac_tx_64 bytes", 0, 0}, - {"mac_tx_65-127 bytes", 0, 0}, - {"mac_tx_128-255 bytes", 0, 0}, - {"mac_tx_256-511 bytes", 0, 0}, - {"mac_tx_512-1023 bytes", 0, 0}, - {"mac_tx_1024-1518 bytes", 0, 0}, - {"mac_tx_1519-max bytes", 0, 0}, - {"mac_rx_all_bytes", 0, 0}, - {"mac_rx_fcs_err", 0, 0}, - {"mac_rx_vlan_frame", 0, 0}, - {"mac_rx_undersized", 0, 0}, - {"mac_rx_control_frame", 0, 0}, - {"mac_rx_frame_discard_not_trunc", 0, 0}, - {"mac_tx_all_bytes", 0, 0}, - {"mac_tx_fcs_err", 0, 0}, - {"mac_tx_vlan_frame", 0, 0}, - {"mac_tx_all_frame", 0, 0}, - {"mac_tx_control_frame", 0, 0}, +#define DPAA2_XSTAT_MAX_NUM \ + (sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)) + +#define DPAA2_DPNI_XSTAT_MAX_NUM \ + (offsetof(struct dpaa2_xstats_seq, mac_cnt) / sizeof(uint64_t)) + +#define DPAA2_MAC_XSTAT_MAX_NUM DPAA2_MAC_NUM_STATS + +static_assert((DPAA2_DPNI_XSTAT_MAX_NUM + DPAA2_MAC_XSTAT_MAX_NUM) == DPAA2_XSTAT_MAX_NUM); + +#define DPAA2_DPNI_STAT_SET_PAGE_PARAM(param) \ +({ \ + int ret = false; \ + \ + if ((id) >= this_offset && (id) < (this_offset + pg_size)) { \ + _stat_id = (id) - this_offset; \ + _param = param; \ + _size = pg_size; \ + ret = true; \ + } \ + ret; \ +}) + +#define DPAA2_DPNI_STAT_PAGE_PARAM(pid) \ +({ \ + uint64_t this_offset = offsetof(struct dpaa2_xstats_seq, pg##pid) / sizeof(uint64_t); \ + uint64_t pg_size = sizeof(struct dpni_statistics_page_##pid) / sizeof(uint64_t); \ + int ret; \ + \ + ret = DPAA2_DPNI_STAT_SET_PAGE_PARAM(0); \ + if (!ret) \ + _page++; \ + ret; \ +}) + +#define DPAA2_DPNI_STAT_POLICER_PAGE_PARAM() \ +({ \ + int ret = false; \ + uint8_t tc_id; \ + uint64_t this_offset; \ + uint64_t pg_size = sizeof(struct dpni_statistics_page_5) / sizeof(uint64_t); \ + \ + for (tc_id = 0; tc_id < MAX_TCS; tc_id++) { \ + this_offset = offsetof(struct dpaa2_xstats_seq, pg5[tc_id]) / sizeof(uint64_t); \ + ret = DPAA2_DPNI_STAT_SET_PAGE_PARAM(tc_id); \ + if (ret) \ + break; \ + } \ + if (!ret) \ + _page++; \ + ret; \ +}) + +static inline int +dpaa2_xstats_id_parse(uint32_t id, uint8_t *page, + uint8_t *stat_id, uint16_t *param, uint16_t *size) +{ + uint8_t _page = DPNI_INGRESS_STATISTICS_PAGE_ID, _stat_id = 0; + uint16_t _param = 0, _size = 0; + + if (DPAA2_DPNI_STAT_PAGE_PARAM(0)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(1)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(2)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(3)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(4)) + goto found_id; + if (DPAA2_DPNI_STAT_POLICER_PAGE_PARAM()) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(6)) + goto found_id; + + DPAA2_PMD_ERR("ID(%d) was not found in DPNI page statistics", id); + return -EINVAL; + +found_id: + if (page) + *page = _page; + if (stat_id) + *stat_id = _stat_id; + if (param) + *param = _param; + if (size) + *size = _size; + + return 0; +} + +/* The field name is used both as a designator and stringified, so it must + * appear twice. Only literal member names are ever passed in. + */ +#define DPAA2_XSTAT_STR_SET(pg, field) \ + .pg.field = (uint64_t)RTE_STR(field) + +#define DPAA2_XSTAT_TC_STR_SET(pg, tc, field) \ + .pg[tc].field = (uint64_t)("TC" RTE_STR(tc) "_" RTE_STR(field)) + +#define MAC_STR(name) ("mac_" #name) +#define MAC_STR_ADDR(name) ((size_t)MAC_STR(name)) + +static const struct dpaa2_xstats_seq dpaa2_xstats_strings = { + DPAA2_XSTAT_STR_SET(pg0, ingress_all_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_all_bytes), + DPAA2_XSTAT_STR_SET(pg0, ingress_multicast_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_multicast_bytes), + DPAA2_XSTAT_STR_SET(pg0, ingress_broadcast_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_broadcast_bytes), + + DPAA2_XSTAT_STR_SET(pg1, egress_all_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_all_bytes), + DPAA2_XSTAT_STR_SET(pg1, egress_multicast_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_multicast_bytes), + DPAA2_XSTAT_STR_SET(pg1, egress_broadcast_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_broadcast_bytes), + + DPAA2_XSTAT_STR_SET(pg2, ingress_filtered_frames), + DPAA2_XSTAT_STR_SET(pg2, ingress_discarded_frames), + DPAA2_XSTAT_STR_SET(pg2, ingress_nobuffer_discards), + DPAA2_XSTAT_STR_SET(pg2, egress_discarded_frames), + DPAA2_XSTAT_STR_SET(pg2, egress_confirmed_frames), + + DPAA2_XSTAT_STR_SET(pg3, ceetm_dequeue_bytes), + DPAA2_XSTAT_STR_SET(pg3, ceetm_dequeue_frames), + DPAA2_XSTAT_STR_SET(pg3, ceetm_reject_bytes), + DPAA2_XSTAT_STR_SET(pg3, ceetm_reject_frames), + + DPAA2_XSTAT_STR_SET(pg4, cgr_reject_frames), + DPAA2_XSTAT_STR_SET(pg4, cgr_reject_bytes), + + DPAA2_XSTAT_TC_STR_SET(pg5, 0, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 0, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 0, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 0, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 0, policer_cnt_re_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 1, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 1, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 1, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 1, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 1, policer_cnt_re_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 2, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 2, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 2, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 2, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 2, policer_cnt_re_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 3, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 3, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 3, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 3, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 3, policer_cnt_re_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 4, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 4, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 4, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 4, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 4, policer_cnt_re_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 5, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 5, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 5, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 5, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 5, policer_cnt_re_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 6, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 6, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 6, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 6, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 6, policer_cnt_re_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 7, policer_cnt_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 7, policer_cnt_yellow), + DPAA2_XSTAT_TC_STR_SET(pg5, 7, policer_cnt_green), + DPAA2_XSTAT_TC_STR_SET(pg5, 7, policer_cnt_re_red), + DPAA2_XSTAT_TC_STR_SET(pg5, 7, policer_cnt_re_yellow), + + DPAA2_XSTAT_STR_SET(pg6, tx_pending_frames_cnt), + + .mac_cnt.rx_64_bytes = MAC_STR_ADDR(rx_64_bytes), + .mac_cnt.rx_65_127_bytes = MAC_STR_ADDR(rx_65_127_bytes), + .mac_cnt.rx_128_255_bytes = MAC_STR_ADDR(rx_128_255_bytes), + .mac_cnt.rx_256_511_bytes = MAC_STR_ADDR(rx_256_511_bytes), + .mac_cnt.rx_512_1023_bytes = MAC_STR_ADDR(rx_512_1023_bytes), + .mac_cnt.rx_1024_1518_bytes = MAC_STR_ADDR(rx_1024_1518_bytes), + .mac_cnt.rx_1519_max_bytes = MAC_STR_ADDR(rx_1519_max_bytes), + + .mac_cnt.rx_fragments = MAC_STR_ADDR(rx_fragments), + .mac_cnt.rx_jabber = MAC_STR_ADDR(rx_jabber), + .mac_cnt.rx_drop_fifo = MAC_STR_ADDR(rx_drop_fifo), + .mac_cnt.rx_alignment_error = MAC_STR_ADDR(rx_alignment_error), + + .mac_cnt.tx_undersize_good = MAC_STR_ADDR(tx_undersize_good), + .mac_cnt.rx_oversize_good = MAC_STR_ADDR(rx_oversize_good), + + .mac_cnt.rx_pause = MAC_STR_ADDR(rx_pause), + .mac_cnt.tx_pause = MAC_STR_ADDR(tx_pause), + + .mac_cnt.rx_good_bytes = MAC_STR_ADDR(rx_good_bytes), + .mac_cnt.rx_multicast = MAC_STR_ADDR(rx_multicast), + .mac_cnt.rx_broadcast = MAC_STR_ADDR(rx_broadcast), + .mac_cnt.rx_all_frames = MAC_STR_ADDR(rx_all_frames), + .mac_cnt.rx_unicast = MAC_STR_ADDR(rx_unicast), + .mac_cnt.rx_error = MAC_STR_ADDR(rx_error), + + .mac_cnt.tx_good_bytes = MAC_STR_ADDR(tx_good_bytes), + .mac_cnt.tx_multicast = MAC_STR_ADDR(tx_multicast), + .mac_cnt.tx_broadcast = MAC_STR_ADDR(tx_broadcast), + .mac_cnt.tx_unicast = MAC_STR_ADDR(tx_unicast), + .mac_cnt.tx_error = MAC_STR_ADDR(tx_error), + + .mac_cnt.rx_valid_frames = MAC_STR_ADDR(rx_valid_frames), + .mac_cnt.tx_valid_frames = MAC_STR_ADDR(tx_valid_frames), + + .mac_cnt.tx_64_bytes = MAC_STR_ADDR(tx_64_bytes), + .mac_cnt.tx_65_127_bytes = MAC_STR_ADDR(tx_65_127_bytes), + .mac_cnt.tx_128_255_bytes = MAC_STR_ADDR(tx_128_255_bytes), + .mac_cnt.tx_256_511_bytes = MAC_STR_ADDR(tx_256_511_bytes), + .mac_cnt.tx_512_1023_bytes = MAC_STR_ADDR(tx_512_1023_bytes), + .mac_cnt.tx_1024_1518_bytes = MAC_STR_ADDR(tx_1024_1518_bytes), + .mac_cnt.tx_1519_max_bytes = MAC_STR_ADDR(tx_1519_max_bytes), + + .mac_cnt.rx_bytes_all = MAC_STR_ADDR(rx_bytes_all), + .mac_cnt.rx_crc_error = MAC_STR_ADDR(rx_crc_error), + .mac_cnt.rx_vlan = MAC_STR_ADDR(rx_vlan), + .mac_cnt.rx_undersize_good = MAC_STR_ADDR(rx_undersize_good), + .mac_cnt.rx_ctrl_non_pause = MAC_STR_ADDR(rx_ctrl_non_pause), + .mac_cnt.rx_drop_full = MAC_STR_ADDR(rx_drop_full), + + .mac_cnt.tx_bytes_all = MAC_STR_ADDR(tx_bytes_all), + .mac_cnt.tx_crc_error = MAC_STR_ADDR(tx_crc_error), + .mac_cnt.tx_vlan = MAC_STR_ADDR(tx_vlan), + .mac_cnt.tx_all_frames = MAC_STR_ADDR(tx_all_frames), + .mac_cnt.tx_ctrl_non_pause = MAC_STR_ADDR(tx_ctrl_non_pause), + + .mac_cnt.rx_pfc_class[0] = MAC_STR_ADDR(rx_pfc_class_0), + .mac_cnt.rx_pfc_class[1] = MAC_STR_ADDR(rx_pfc_class_1), + .mac_cnt.rx_pfc_class[2] = MAC_STR_ADDR(rx_pfc_class_2), + .mac_cnt.rx_pfc_class[3] = MAC_STR_ADDR(rx_pfc_class_3), + .mac_cnt.rx_pfc_class[4] = MAC_STR_ADDR(rx_pfc_class_4), + .mac_cnt.rx_pfc_class[5] = MAC_STR_ADDR(rx_pfc_class_5), + .mac_cnt.rx_pfc_class[6] = MAC_STR_ADDR(rx_pfc_class_6), + .mac_cnt.rx_pfc_class[7] = MAC_STR_ADDR(rx_pfc_class_7), + + .mac_cnt.tx_pfc_class[0] = MAC_STR_ADDR(tx_pfc_class_0), + .mac_cnt.tx_pfc_class[1] = MAC_STR_ADDR(tx_pfc_class_1), + .mac_cnt.tx_pfc_class[2] = MAC_STR_ADDR(tx_pfc_class_2), + .mac_cnt.tx_pfc_class[3] = MAC_STR_ADDR(tx_pfc_class_3), + .mac_cnt.tx_pfc_class[4] = MAC_STR_ADDR(tx_pfc_class_4), + .mac_cnt.tx_pfc_class[5] = MAC_STR_ADDR(tx_pfc_class_5), + .mac_cnt.tx_pfc_class[6] = MAC_STR_ADDR(tx_pfc_class_6), + .mac_cnt.tx_pfc_class[7] = MAC_STR_ADDR(tx_pfc_class_7) +}; + +#define DPAA2_DPNI_XSTAT_FIELD_ID(field) \ + (offsetof(struct dpaa2_xstats_seq, field) / sizeof(uint64_t)) + +static const struct rte_eth_stats dpaa2_stats_xstat_ids = { + .ipackets = DPAA2_DPNI_XSTAT_FIELD_ID(pg0.ingress_all_frames), + .opackets = DPAA2_DPNI_XSTAT_FIELD_ID(pg1.egress_all_frames), + .ibytes = DPAA2_DPNI_XSTAT_FIELD_ID(pg0.ingress_all_bytes), + .obytes = DPAA2_DPNI_XSTAT_FIELD_ID(pg1.egress_all_bytes), + .imissed = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_filtered_frames), + .ierrors = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_discarded_frames), + .oerrors = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.egress_discarded_frames), + .rx_nombuf = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_nobuffer_discards) }; +#define DPAA2_STATS_XSTATS_NUM \ + (sizeof(dpaa2_stats_xstat_ids) / sizeof(uint64_t)) + +#define DPAA2_MAC_XSTATS_START_ID DPAA2_DPNI_XSTAT_MAX_NUM + + static struct rte_dpaa2_driver rte_dpaa2_pmd; static int dpaa2_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); @@ -1892,127 +2064,47 @@ dpaa2_dev_set_mac_addr(struct rte_eth_dev *dev, } static int -dpaa2_dev_stats_get(struct rte_eth_dev *dev, - struct rte_eth_stats *stats, struct eth_queue_stats *qstats) +dpaa2_dev_xstat_mac_setup_mem(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - int32_t retcode; - uint8_t page0 = 0, page1 = 1, page2 = 2; - union dpni_statistics value; - int i; - struct dpaa2_queue *dpaa2_rxq, *dpaa2_txq; - - memset(&value, 0, sizeof(union dpni_statistics)); - - PMD_INIT_FUNC_TRACE(); - - if (!dpni) { - DPAA2_PMD_ERR("dpni is NULL"); - return -EINVAL; - } - - if (!stats) { - DPAA2_PMD_ERR("stats is NULL"); - return -EINVAL; - } - - /*Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page0, 0, &value); - if (retcode) - goto err; - - stats->ipackets = value.page_0.ingress_all_frames; - stats->ibytes = value.page_0.ingress_all_bytes; - - /*Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page1, 0, &value); - if (retcode) - goto err; - - stats->opackets = value.page_1.egress_all_frames; - stats->obytes = value.page_1.egress_all_bytes; - - /*Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page2, 0, &value); - if (retcode) - goto err; - - /* Ingress drop frame count due to configured rules */ - stats->ierrors = value.page_2.ingress_filtered_frames; - /* Ingress drop frame count due to error */ - stats->ierrors += value.page_2.ingress_discarded_frames; - - stats->oerrors = value.page_2.egress_discarded_frames; - stats->imissed = value.page_2.ingress_nobuffer_discards; - - /* Fill in per queue stats */ - if (qstats != NULL) { - for (i = 0; (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) && - (i < priv->nb_rx_queues || i < priv->nb_tx_queues); ++i) { - dpaa2_rxq = priv->rx_vq[i]; - dpaa2_txq = priv->tx_vq[i]; - if (dpaa2_rxq) - qstats->q_ipackets[i] = dpaa2_rxq->rx_pkts; - if (dpaa2_txq) - qstats->q_opackets[i] = dpaa2_txq->tx_pkts; + int ret = 0; - /* Byte counting is not implemented */ - qstats->q_ibytes[i] = 0; - qstats->q_obytes[i] = 0; + if (!priv->cnt_idx_dma_mem) { + priv->cnt_idx_dma_mem = rte_zmalloc(NULL, + DPAA2_MAC_STATS_INDEX_DMA_SIZE, RTE_CACHE_LINE_SIZE); + if (!priv->cnt_idx_dma_mem) { + ret = -ENOMEM; + DPAA2_PMD_ERR("Failure to allocate memory for mac index"); + goto out; } - } - - return 0; - -err: - DPAA2_PMD_ERR("Operation not completed:Error Code = %d", retcode); - return retcode; -}; - -void -dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev) -{ - struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint32_t *cnt_idx; - int i; - priv->cnt_idx_dma_mem = rte_malloc(NULL, DPAA2_MAC_STATS_INDEX_DMA_SIZE, - RTE_CACHE_LINE_SIZE); - if (!priv->cnt_idx_dma_mem) { - DPAA2_PMD_ERR("Failure to allocate memory for mac index"); - goto out; + priv->cnt_idx_iova = rte_mem_virt2iova(priv->cnt_idx_dma_mem); + if (priv->cnt_idx_iova == RTE_BAD_IOVA) { + ret = -ENOBUFS; + DPAA2_PMD_ERR("%s: No IOMMU map for count index dma mem(%p)", + __func__, priv->cnt_idx_dma_mem); + goto err_dma_map; + } } - priv->cnt_values_dma_mem = rte_malloc(NULL, DPAA2_MAC_STATS_VALUE_DMA_SIZE, - RTE_CACHE_LINE_SIZE); if (!priv->cnt_values_dma_mem) { - DPAA2_PMD_ERR("Failure to allocate memory for mac values"); - goto err_alloc_values; - } - - cnt_idx = priv->cnt_idx_dma_mem; - for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) - *cnt_idx++ = rte_cpu_to_le_32((uint32_t)i); - - priv->cnt_idx_iova = rte_mem_virt2iova(priv->cnt_idx_dma_mem); - if (priv->cnt_idx_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for count index dma mem(%p)", - __func__, priv->cnt_idx_dma_mem); - goto err_dma_map; - } - - priv->cnt_values_iova = rte_mem_virt2iova(priv->cnt_values_dma_mem); - if (priv->cnt_values_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for count values dma mem(%p)", - __func__, priv->cnt_values_dma_mem); - goto err_dma_map; + priv->cnt_values_dma_mem = rte_zmalloc(NULL, + DPAA2_MAC_STATS_VALUE_DMA_SIZE, RTE_CACHE_LINE_SIZE); + if (!priv->cnt_values_dma_mem) { + ret = -ENOMEM; + DPAA2_PMD_ERR("Failure to allocate memory for mac values"); + goto err_alloc_values; + } + priv->cnt_values_iova = rte_mem_virt2iova(priv->cnt_values_dma_mem); + if (priv->cnt_values_iova == RTE_BAD_IOVA) { + ret = -ENOBUFS; + DPAA2_PMD_ERR("%s: No IOMMU map for count values dma mem(%p)", + __func__, priv->cnt_values_dma_mem); + goto err_dma_map; + } } - return; + return 0; err_dma_map: rte_free(priv->cnt_values_dma_mem); @@ -2021,224 +2113,281 @@ dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev) out: priv->cnt_idx_dma_mem = NULL; priv->cnt_values_dma_mem = NULL; + + return ret; } -/* - * dpaa2_dev_xstats_get(): Get counters of dpni and dpmac. - * MAC (mac_*) counters are supported on MC version > 10.39.0 - * TC_x_policer_* counters are supported only when Policer is enable. - */ static int -dpaa2_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstat *xstats, unsigned int n) +dpaa2_dev_mac_xstats_avail(struct rte_eth_dev *dev) { - struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; - unsigned int i = 0, j = 0, num = RTE_DIM(dpaa2_xstats_strings); struct dpaa2_dev_priv *priv = dev->data->dev_private; - union dpni_statistics value[13] = {}; - struct dpni_rx_tc_policing_cfg cfg; - uint8_t page_id, stats_id; - uint64_t *cnt_values; - int32_t retcode; - int16_t tc; - - if (n < num) - return num; + uint64_t rev_mac_support; - if (!xstats) - return 0; - /* Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 0, 0, &value[0]); - if (retcode) - goto err; - - /* Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 1, 0, &value[1]); - if (retcode) - goto err; - - /* Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 2, 0, &value[2]); - if (retcode) - goto err; - - for (j = 0; j < priv->max_cgs; j++) { - if (!priv->cgid_in_use[j]) { - /* Get Counters from page_4*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, - priv->token, - 4, 0, &value[4]); - if (retcode) - goto err; - break; - } - } + if (priv->ep_dev_type != DPAA2_MAC) + return false; - for (tc = 0; tc < priv->num_rx_tc; tc++) { - retcode = dpni_get_rx_tc_policing(dpni, CMD_PRI_LOW, - priv->token, tc, - &cfg); - if (retcode) { - DPAA2_PMD_ERR("Error to get the policer rule: %d", retcode); - goto err; - } + rev_mac_support = RTE_FSL_MC_REV(MC_VER_MAJOR, MC_VER_MINOR, 0); + if (priv->mc_rev >= rev_mac_support) + return true; - /* get policer stats if policer is enabled */ - if (cfg.mode != 0) { - /* Get Counters from page_5*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, - priv->token, 5, tc, - &value[(tc + 5)]); - if (retcode) - goto err; - } - } + return false; +} - while (i < (num - DPAA2_MAC_NUM_STATS)) { - xstats[i].id = i; - page_id = dpaa2_xstats_strings[i].page_id; - stats_id = dpaa2_xstats_strings[i].stats_id; - xstats[i].value = value[page_id].raw.counter[stats_id]; - i++; - } +static int +dpaa2_dev_dpni_xstats_avail(struct rte_eth_dev *dev, + uint8_t page_id, uint16_t param) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + uint8_t tc, i; - if (priv->cnt_idx_dma_mem && - !dpni_get_mac_statistics(dpni, CMD_PRI_LOW, priv->token, - priv->cnt_idx_iova, - priv->cnt_values_iova, - DPAA2_MAC_NUM_STATS)) { - cnt_values = priv->cnt_values_dma_mem; - while (i >= (num - DPAA2_MAC_NUM_STATS) && i < num) { - xstats[i].id = i; - xstats[i].value = rte_le_to_cpu_64(*cnt_values++); - i++; + if (page_id == DPNI_CGR_STATISTICS_PAGE_ID) { + for (i = 0; i < priv->max_cgs; i++) { + if (priv->cgid_in_use[i]) + return true; } - return i; - } - - while (i >= (num - DPAA2_MAC_NUM_STATS) && i < num) { - xstats[i].id = i; - xstats[i].value = 0; - i++; + } else if (page_id == DPNI_POLICER_STATISTICS_PAGE_ID) { + tc = param; + if (tc < MAX_TCS) + return true; + } else { + return true; } - return i; -err: - DPAA2_PMD_ERR("Error in obtaining extended stats (%d)", retcode); - return retcode; + return false; } static int -dpaa2_xstats_get_names(__rte_unused struct rte_eth_dev *dev, - struct rte_eth_xstat_name *xstats_names, - unsigned int limit) +dpaa2_dev_xstats_get_names(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, uint32_t limit) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); + uint16_t i, stat_cnt; + uint64_t xstat_str[DPAA2_XSTAT_MAX_NUM]; + + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; + + if (!limit) + return stat_cnt; if (limit < stat_cnt) + stat_cnt = limit; + + if (!xstats_names) return stat_cnt; - if (xstats_names != NULL) - for (i = 0; i < stat_cnt; i++) - strlcpy(xstats_names[i].name, - dpaa2_xstats_strings[i].name, - sizeof(xstats_names[i].name)); + rte_memcpy(xstat_str, &dpaa2_xstats_strings, sizeof(xstat_str)); + + for (i = 0; i < stat_cnt; i++) + rte_strscpy(xstats_names[i].name, (char *)xstat_str[i], RTE_ETH_XSTATS_NAME_SIZE); return stat_cnt; } static int -dpaa2_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, - uint64_t *values, unsigned int n) +dpaa2_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, + uint64_t *values, uint32_t n) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); - uint64_t values_copy[stat_cnt]; - uint8_t page_id, stats_id; - - if (!ids) { - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - int32_t retcode; - union dpni_statistics value[5] = {}; - - if (n < stat_cnt) - return stat_cnt; - - if (!values) - return 0; + uint16_t i, id, stat_cnt, mac_num = 0; + uint8_t page_id, stat_id; + uint16_t param; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = dev->process_private; + bool page_fetched[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; + /* Fetch required MAC counters in a single MC command. */ + int retcode; + uint32_t *mac_idx; + uint64_t *mac_val[DPAA2_MAC_XSTAT_MAX_NUM]; - /* Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 0, 0, &value[0]); - if (retcode) - return 0; + retcode = dpaa2_dev_xstat_mac_setup_mem(dev); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to setup %s's MAC statistics!", + __func__, retcode, dev->data->name); + return retcode; + } + mac_idx = priv->cnt_idx_dma_mem; - /* Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 1, 0, &value[1]); - if (retcode) - return 0; + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; - /* Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 2, 0, &value[2]); - if (retcode) - return 0; + memset(page_fetched, 0, sizeof(page_fetched)); - /* Get Counters from page_4*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 4, 0, &value[4]); + for (i = 0; i < n; i++) { + if (ids && ids[i] >= stat_cnt) { + DPAA2_PMD_ERR("xstats id value isn't valid"); + return -EINVAL; + } + id = ids ? ids[i] : i; + if (id >= DPAA2_MAC_XSTATS_START_ID) { + values[i] = 0; + if (dpaa2_dev_mac_xstats_avail(dev)) { + mac_idx[mac_num] = rte_cpu_to_le_32(id - DPAA2_MAC_XSTATS_START_ID); + mac_val[mac_num] = &values[i]; + mac_num++; + } + continue; + } + page_id = 0; + stat_id = 0; + param = 0; + retcode = dpaa2_xstats_id_parse(id, &page_id, &stat_id, ¶m, NULL); if (retcode) - return 0; - - for (i = 0; i < stat_cnt; i++) { - page_id = dpaa2_xstats_strings[i].page_id; - stats_id = dpaa2_xstats_strings[i].stats_id; - values[i] = value[page_id].raw.counter[stats_id]; + return retcode; + if (!dpaa2_dev_dpni_xstats_avail(dev, page_id, param)) { + values[i] = 0; + continue; } - return stat_cnt; + if (page_fetched[page_id][param]) { + values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; + continue; + } + /* Cache dpni page results: multiple xstats can share + * the same (page_id, param), so only fetch each pair once. + */ + retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, + priv->token, page_id, param, + &priv->pg_xstats[page_id][param]); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's statistcis of page%d!", + __func__, retcode, dev->data->name, page_id); + return retcode; + } + page_fetched[page_id][param] = true; + values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; } - dpaa2_xstats_get_by_id(dev, NULL, values_copy, stat_cnt); - - for (i = 0; i < n; i++) { - if (ids[i] >= stat_cnt) { - DPAA2_PMD_ERR("xstats id value isn't valid"); - return -EINVAL; + if (mac_num > 0) { + retcode = dpni_get_mac_statistics(dpni, CMD_PRI_LOW, + priv->token, priv->cnt_idx_iova, + priv->cnt_values_iova, mac_num); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's %d MAC statistics!", + __func__, retcode, dev->data->name, mac_num); + return retcode; } - values[i] = values_copy[ids[i]]; + for (i = 0; i < mac_num; i++) + *mac_val[i] = priv->cnt_values_dma_mem[i]; } + return n; } static int -dpaa2_xstats_get_names_by_id(struct rte_eth_dev *dev, - const uint64_t *ids, - struct rte_eth_xstat_name *xstats_names, - unsigned int limit) +dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, + const uint64_t *ids, struct rte_eth_xstat_name *xstats_names, + uint32_t limit) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); - struct rte_eth_xstat_name xstats_names_copy[stat_cnt]; + uint16_t i, stat_cnt; + uint64_t xstat_str[DPAA2_XSTAT_MAX_NUM]; + + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; if (!ids) - return dpaa2_xstats_get_names(dev, xstats_names, limit); + return dpaa2_dev_xstats_get_names(dev, xstats_names, limit); - dpaa2_xstats_get_names(dev, xstats_names_copy, limit); + rte_memcpy(xstat_str, &dpaa2_xstats_strings, sizeof(xstat_str)); for (i = 0; i < limit; i++) { if (ids[i] >= stat_cnt) { - DPAA2_PMD_ERR("xstats id value isn't valid"); - return -1; + DPAA2_PMD_ERR("xstats id[%d] value(%" PRIu64 ") >= max count(%d)", + i, ids[i], stat_cnt); + return -EINVAL; } - strcpy(xstats_names[i].name, xstats_names_copy[ids[i]].name); + rte_strscpy(xstats_names[i].name, + (char *)xstat_str[ids[i]], RTE_ETH_XSTATS_NAME_SIZE); } return limit; } +/* + * dpaa2_dev_xstats_get(): Get counters of dpni and dpmac. + * MAC (mac_*) counters are supported on MC version > 10.39.0 + * TC_x_policer_* counters are supported only when Policer is enable. + */ +static int +dpaa2_dev_xstats_get(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, uint32_t n) +{ + int retcode; + uint32_t i; + uint64_t ids[DPAA2_XSTAT_MAX_NUM], vals[DPAA2_XSTAT_MAX_NUM]; + + if (!xstats || !n) + return 0; + + if (n > DPAA2_XSTAT_MAX_NUM) { + DPAA2_PMD_WARN("%s: Expected xstat number(%d) > max(%zu)", + __func__, n, (size_t)DPAA2_XSTAT_MAX_NUM); + n = DPAA2_XSTAT_MAX_NUM; + } + for (i = 0; i < n; i++) { + ids[i] = i; + xstats[i].id = i; + xstats[i].value = 0; + } + + retcode = dpaa2_dev_xstats_get_by_id(dev, ids, vals, n); + if (retcode < 0) + return retcode; + + for (i = 0; i < (uint32_t)retcode; i++) + xstats[i].value = vals[i]; + + return retcode; +} + +static int +dpaa2_dev_stats_get(struct rte_eth_dev *dev, + struct rte_eth_stats *stats, struct eth_queue_stats *qstats) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int32_t retcode; + uint16_t i, num; + uint64_t ids[DPAA2_STATS_XSTATS_NUM], counts[DPAA2_STATS_XSTATS_NUM] = {0}; + struct dpaa2_queue *dpaa2_q; + + PMD_INIT_FUNC_TRACE(); + + rte_memcpy(ids, &dpaa2_stats_xstat_ids, sizeof(dpaa2_stats_xstat_ids)); + retcode = dpaa2_dev_xstats_get_by_id(dev, ids, counts, DPAA2_STATS_XSTATS_NUM); + if (retcode != RTE_DIM(ids)) { + DPAA2_PMD_ERR("%s: Failed to get xstats (%d)counters by %zu IDs", + __func__, retcode, (size_t)DPAA2_STATS_XSTATS_NUM); + if (retcode >= 0) + retcode = -EINVAL; + return retcode; + } + + rte_memcpy(stats, counts, sizeof(struct rte_eth_stats)); + stats->imissed += stats->ierrors + stats->rx_nombuf; + + if (qstats) { + /* Fill in per queue stats */ + num = RTE_MIN(priv->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS); + for (i = 0; i < num; i++) { + dpaa2_q = priv->rx_vq[i]; + qstats->q_ipackets[i] = dpaa2_q->rx_pkts; + + /* Byte counting is not implemented */ + qstats->q_ibytes[i] = 0; + } + num = RTE_MIN(priv->nb_tx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS); + for (i = 0; i < num; i++) { + dpaa2_q = priv->tx_vq[i]; + qstats->q_opackets[i] = dpaa2_q->tx_pkts; + + /* Byte counting is not implemented */ + qstats->q_obytes[i] = 0; + } + } + + return 0; +} + static int dpaa2_dev_stats_reset(struct rte_eth_dev *dev) { @@ -2255,7 +2404,7 @@ dpaa2_dev_stats_reset(struct rte_eth_dev *dev) return -EINVAL; } - retcode = dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token); + retcode = dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token); if (retcode) goto error; @@ -3262,9 +3411,9 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .link_update = dpaa2_dev_link_update, .stats_get = dpaa2_dev_stats_get, .xstats_get = dpaa2_dev_xstats_get, - .xstats_get_by_id = dpaa2_xstats_get_by_id, - .xstats_get_names_by_id = dpaa2_xstats_get_names_by_id, - .xstats_get_names = dpaa2_xstats_get_names, + .xstats_get_by_id = dpaa2_dev_xstats_get_by_id, + .xstats_get_names_by_id = dpaa2_dev_xstats_get_names_by_id, + .xstats_get_names = dpaa2_dev_xstats_get_names, .stats_reset = dpaa2_dev_stats_reset, .xstats_reset = dpaa2_dev_stats_reset, .fw_version_get = dpaa2_fw_version_get, @@ -3719,17 +3868,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); - /* mac_statistics supported on MC version > 10.39.0 */ - { - struct mc_version mc_ver_info = {0}; - - if (!mc_get_version(dpni_dev, CMD_PRI_LOW, &mc_ver_info) && - mc_ver_info.major >= MC_VER_MAJOR && - mc_ver_info.minor >= MC_VER_MINOR && - mc_ver_info.revision > 0) - dpaa2_dev_mac_setup_stats(eth_dev); - } - return 0; init_err: dpaa2_dev_close(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e7490b1e0c..523c420c51 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -203,7 +203,8 @@ (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ -#define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) +#define DPAA2_MAC_NUM_STATS \ + (sizeof(struct dpni_dpmac_counters) / sizeof(uint64_t)) #define DPAA2_MAC_STATS_INDEX_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint32_t)) #define DPAA2_MAC_STATS_VALUE_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint64_t)) @@ -540,6 +541,12 @@ struct dpaa2_dev_priv { uint64_t cnt_idx_iova, cnt_values_iova; uint64_t mc_rev; + /* Cache one dpni_statistics result per (page_id, param) pair to avoid + * redundant MC commands when multiple xstats share the same page. + * Put it in heap to avoid allocating multi-KB stack in runtime. + */ + union dpni_statistics pg_xstats[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; + struct rte_mempool *tx_sg_pool; struct dpaa2_dev_flow *curr; @@ -703,7 +710,4 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); -void -dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); - #endif /* _DPAA2_ETHDEV_H */ diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index f315bb7004..bc895234f1 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -688,50 +688,77 @@ int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, * @page_6.tx_pending_frames_cnt: total number of frames pending in Tx queues * @raw: raw statistics structure, used to index counters */ +enum dpni_statistics_page_id { + DPNI_INGRESS_STATISTICS_PAGE_ID = 0, + DPNI_EGRESS_STATISTICS_PAGE_ID = 1, + DPNI_ERR_STATISTICS_PAGE_ID = 2, + DPNI_CEETM_STATISTICS_PAGE_ID = 3, + DPNI_CGR_STATISTICS_PAGE_ID = 4, + DPNI_POLICER_STATISTICS_PAGE_ID = 5, + DPNI_TX_PENDING_STATISTICS_PAGE_ID = 6, + DPNI_MAX_STATISTICS_PAGE_ID +}; + +struct dpni_statistics_page_0 { + uint64_t ingress_all_frames; + uint64_t ingress_all_bytes; + uint64_t ingress_multicast_frames; + uint64_t ingress_multicast_bytes; + uint64_t ingress_broadcast_frames; + uint64_t ingress_broadcast_bytes; +}; + +struct dpni_statistics_page_1 { + uint64_t egress_all_frames; + uint64_t egress_all_bytes; + uint64_t egress_multicast_frames; + uint64_t egress_multicast_bytes; + uint64_t egress_broadcast_frames; + uint64_t egress_broadcast_bytes; +}; + +struct dpni_statistics_page_2 { + uint64_t ingress_filtered_frames; + uint64_t ingress_discarded_frames; + uint64_t ingress_nobuffer_discards; + uint64_t egress_discarded_frames; + uint64_t egress_confirmed_frames; +}; + +struct dpni_statistics_page_3 { + uint64_t ceetm_dequeue_bytes; + uint64_t ceetm_dequeue_frames; + uint64_t ceetm_reject_bytes; + uint64_t ceetm_reject_frames; +}; + +struct dpni_statistics_page_4 { + uint64_t cgr_reject_frames; + uint64_t cgr_reject_bytes; +}; + +struct dpni_statistics_page_5 { + uint64_t policer_cnt_red; + uint64_t policer_cnt_yellow; + uint64_t policer_cnt_green; + uint64_t policer_cnt_re_red; + uint64_t policer_cnt_re_yellow; +}; + +struct dpni_statistics_page_6 { + uint64_t tx_pending_frames_cnt; +}; + +#define DPNI_STAT_MAX_PARAM DPNI_MAX_TC + union dpni_statistics { - struct { - uint64_t ingress_all_frames; - uint64_t ingress_all_bytes; - uint64_t ingress_multicast_frames; - uint64_t ingress_multicast_bytes; - uint64_t ingress_broadcast_frames; - uint64_t ingress_broadcast_bytes; - } page_0; - struct { - uint64_t egress_all_frames; - uint64_t egress_all_bytes; - uint64_t egress_multicast_frames; - uint64_t egress_multicast_bytes; - uint64_t egress_broadcast_frames; - uint64_t egress_broadcast_bytes; - } page_1; - struct { - uint64_t ingress_filtered_frames; - uint64_t ingress_discarded_frames; - uint64_t ingress_nobuffer_discards; - uint64_t egress_discarded_frames; - uint64_t egress_confirmed_frames; - } page_2; - struct { - uint64_t ceetm_dequeue_bytes; - uint64_t ceetm_dequeue_frames; - uint64_t ceetm_reject_bytes; - uint64_t ceetm_reject_frames; - } page_3; - struct { - uint64_t cgr_reject_frames; - uint64_t cgr_reject_bytes; - } page_4; - struct { - uint64_t policer_cnt_red; - uint64_t policer_cnt_yellow; - uint64_t policer_cnt_green; - uint64_t policer_cnt_re_red; - uint64_t policer_cnt_re_yellow; - } page_5; - struct { - uint64_t tx_pending_frames_cnt; - } page_6; + struct dpni_statistics_page_0 page_0; + struct dpni_statistics_page_1 page_1; + struct dpni_statistics_page_2 page_2; + struct dpni_statistics_page_3 page_3; + struct dpni_statistics_page_4 page_4; + struct dpni_statistics_page_5 page_5; + struct dpni_statistics_page_6 page_6; struct { uint64_t counter[DPNI_STATISTICS_CNT]; } raw; @@ -2147,9 +2174,151 @@ int dpni_set_sp_profile(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t to int dpni_sp_enable(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t type, uint8_t en); -int dpni_get_mac_statistics(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, - uint64_t iova_cnt, uint64_t iova_values, uint32_t num_cnt); +struct dpni_dpmac_counters { + /** 0x00: Counts received 64-bytes frames, good or bad */ + uint64_t rx_64_bytes; + + /** 0x01: Counts received 65- to 127-bytes frames, good or bad */ + uint64_t rx_65_127_bytes; + + /** 0x02: Counts received 128- to 255-bytes frames, good or bad */ + uint64_t rx_128_255_bytes; + + /** 0x03: Counts received 256- to 511-bytes frames, good or bad */ + uint64_t rx_256_511_bytes; + + /** 0x04: Counts received 512- to 1023-bytes frames, good or bad */ + uint64_t rx_512_1023_bytes; + + /** 0x05: Counts received 1024- to 1518-bytes frames, good or bad */ + uint64_t rx_1024_1518_bytes; + + /** 0x06: Counts received frames >=1519 bytes */ + uint64_t rx_1519_max_bytes; + + /** 0x07: <64B frames with bad CRC */ + uint64_t rx_fragments; + + /** 0x08: >max length frames with bad FCS */ + uint64_t rx_jabber; + + /** 0x09: FIFO overflow drops (including truncated frames) */ + uint64_t rx_drop_fifo; + + /** 0x0A: Alignment error frames */ + uint64_t rx_alignment_error; + + /** 0x0B: TX <64B frames with good CRC */ + uint64_t tx_undersize_good; + /** 0x0C: >max length frames with good FCS */ + uint64_t rx_oversize_good; + + /** 0x0D: Received pause frames (including PFC) */ + uint64_t rx_pause; + + /** 0x0E: Transmitted pause frames (including PFC) */ + uint64_t tx_pause; + + /** 0x0F: Received bytes (valid frames, exclude preamble) */ + uint64_t rx_good_bytes; + + /** 0x10: Received multicast frames */ + uint64_t rx_multicast; + + /** 0x11: Received broadcast frames */ + uint64_t rx_broadcast; + + /** 0x12: Received frames (good + bad) */ + uint64_t rx_all_frames; + + /** 0x13: Received unicast frames */ + uint64_t rx_unicast; + + /** 0x14: Received error frames (excluding fragments) */ + uint64_t rx_error; + + /** 0x15: Transmitted bytes (valid frames) */ + uint64_t tx_good_bytes; + + /** 0x16: Transmitted multicast frames */ + uint64_t tx_multicast; + + /** 0x17: Transmitted broadcast frames */ + uint64_t tx_broadcast; + + /** 0x18: Transmitted unicast frames */ + uint64_t tx_unicast; + + /** 0x19: Transmitted error frames */ + uint64_t tx_error; + + /** 0x1A: Received valid frames (no error) */ + uint64_t rx_valid_frames; + + /** 0x1B: Transmitted valid frames (no error) */ + uint64_t tx_valid_frames; + + /** 0x1C: TX 64-byte frames */ + uint64_t tx_64_bytes; + + /** 0x1D: TX 65-127-byte frames */ + uint64_t tx_65_127_bytes; + + /** 0x1E: TX 128-255-byte frames */ + uint64_t tx_128_255_bytes; + + /** 0x1F: TX 256-511-byte frames */ + uint64_t tx_256_511_bytes; + + /** 0x20: TX 512-1023-byte frames */ + uint64_t tx_512_1023_bytes; + + /** 0x21: TX 1024-1518-byte frames */ + uint64_t tx_1024_1518_bytes; + + /** 0x22: TX >=1519-byte frames */ + uint64_t tx_1519_max_bytes; + + /** 0x23: RX bytes (good + bad frames) */ + uint64_t rx_bytes_all; + + /** 0x24: RX CRC-32 error frames */ + uint64_t rx_crc_error; + + /** 0x25: Valid VLAN-tagged RX frames */ + uint64_t rx_vlan; + + /** 0x26: RX <64B frames with good CRC */ + uint64_t rx_undersize_good; + + /** 0x27: RX control frames (0x8808, non-pause) */ + uint64_t rx_ctrl_non_pause; + + /** 0x28: Fully dropped frames due to MAC client FIFO overflow */ + uint64_t rx_drop_full; + + /** 0x29: TX bytes (good + bad frames) */ + uint64_t tx_bytes_all; + + /** 0x2A: TX CRC-32 error frames */ + uint64_t tx_crc_error; + + /** 0x2B: Valid VLAN-tagged TX frames */ + uint64_t tx_vlan; + + /** 0x2C: All TX frames (good + bad) */ + uint64_t tx_all_frames; + + /** 0x2D: TX control frames (0x8808, non-pause) */ + uint64_t tx_ctrl_non_pause; + + /** 0x2E-0x35: RX PFC frames per priority (0-7) */ + uint64_t rx_pfc_class[DPNI_MAX_TC]; + + /** 0x36-0x3D: TX PFC frames per priority (0-7) */ + uint64_t tx_pfc_class[DPNI_MAX_TC]; +}; int dpni_get_mac_statistics(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint64_t iova_cnt, uint64_t iova_values, uint32_t num_cnt); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 37/45] net/dpaa2: rework flow engine 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (35 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 36/45] net/dpaa2: enhance xstat implementation Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 38/45] net/dpaa2: support Rx mempool per traffic class Prashant Gupta ` (13 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Rework the dpaa2 flow engine so that flow rules are programmed through the updated QoS and flow steering (FS) table interface. The distribution helpers in base/dpaa2_hw_dpni.c are removed and folded into the ethdev and flow code, which removes a layer of indirection and keeps the key extraction, RSS distribution and QoS/FS entry programming together in one place. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 546 -- drivers/net/dpaa2/dpaa2_ethdev.c | 457 +- drivers/net/dpaa2/dpaa2_ethdev.h | 478 +- drivers/net/dpaa2/dpaa2_flow.c | 6906 ++++++++++++++---------- drivers/net/dpaa2/meson.build | 3 +- 5 files changed, 4719 insertions(+), 3671 deletions(-) delete mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni.c diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c deleted file mode 100644 index fee96b3529..0000000000 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c +++ /dev/null @@ -1,546 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2021,2023-2025 NXP - * - */ - -#include <time.h> -#include <net/if.h> - -#include <eal_export.h> -#include <rte_mbuf.h> -#include <ethdev_driver.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <rte_cycles.h> -#include <rte_kvargs.h> -#include <dev_driver.h> - -#include <dpaa2_pmd_logs.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_mempool.h> - -#include "../dpaa2_ethdev.h" - -int -dpaa2_distset_to_dpkg_profile_cfg( - uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg); - -RTE_EXPORT_SYMBOL(rte_pmd_dpaa2_set_custom_hash) -int -rte_pmd_dpaa2_set_custom_hash(uint16_t port_id, - uint16_t offset, uint8_t size) -{ - struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; - struct dpni_rx_tc_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret, tc_index = 0; - - if (!rte_eth_dev_is_valid_port(port_id)) { - DPAA2_PMD_WARN("Invalid port id %u", port_id); - return -EINVAL; - } - - if (strcmp(eth_dev->device->driver->name, - RTE_STR(NET_DPAA2_PMD_DRIVER_NAME))) { - DPAA2_PMD_WARN("Not a valid dpaa2 port"); - return -EINVAL; - } - - p_params = rte_zmalloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(&kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); - kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_DATA; - kg_cfg.extracts[0].extract.from_data.offset = offset; - kg_cfg.extracts[0].extract.from_data.size = size; - kg_cfg.extracts[0].num_of_byte_masks = 0; - kg_cfg.num_extracts = 1; - - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.dist_size = eth_dev->data->nb_rx_queues; - tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; - - ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, - &tc_cfg); - rte_free(p_params); - if (ret) { - DPAA2_PMD_ERR("Set RX TC dist failed(err=%d)", ret); - return ret; - } - - return 0; -} - -int -dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - int tc_dist_queues; - - /* TC distribution size is set with dist_queues or - * (nb_rx_queues - tc_index*dist_queues) in order of TC priority index. - */ - tc_dist_queues = eth_dev->data->nb_rx_queues - - tc_index * priv->dist_queues; - if (tc_dist_queues <= 0) { - DPAA2_PMD_INFO("No distribution on TC%d", tc_index); - return 0; - } - - if (tc_dist_queues > priv->dist_queues) - tc_dist_queues = priv->dist_queues; - - return dpaa2_setup_flow_dist_size(eth_dev, req_dist_set, - tc_index, tc_dist_queues); -} - -int -dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index, uint16_t dist_size) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = eth_dev->process_private; - struct dpni_rx_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret; - - if (dist_size == 0) - return 0; - - p_params = rte_malloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(p_params, 0, DIST_PARAM_IOVA_SIZE); - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - - ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg); - if (ret) { - DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported", - req_dist_set); - rte_free(p_params); - return ret; - } - - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.dist_size = dist_size; - tc_cfg.enable = true; - tc_cfg.tc = tc_index; - - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); - rte_free(p_params); - if (ret) { - DPAA2_PMD_ERR("RX Hash dist for failed(err=%d)", ret); - return ret; - } - - if (tc_index < MAX_TCS) - priv->dist_size_cur[tc_index] = dist_size; - - return 0; -} - -int -dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev, - uint8_t tc_index) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; - struct dpni_rx_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret; - - p_params = rte_malloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - tc_cfg.dist_size = 0; - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.enable = true; - tc_cfg.tc = tc_index; - - memset(p_params, 0, DIST_PARAM_IOVA_SIZE); - kg_cfg.num_extracts = 0; - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, - &tc_cfg); - rte_free(p_params); - if (ret) - DPAA2_PMD_ERR("RX hash dist failed(err=%d)", ret); - return ret; -} - -int -dpaa2_distset_to_dpkg_profile_cfg( - uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg) -{ - uint32_t loop = 0, i = 0; - uint64_t dist_field = 0; - int l2_configured = 0, l3_configured = 0; - int l4_configured = 0; - int mpls_configured = 0; - int vlan_configured = 0; - int esp_configured = 0; - int ah_configured = 0; - int pppoe_configured = 0; - - memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); - while (req_dist_set) { - if (req_dist_set % 2 != 0) { - dist_field = 1ULL << loop; - switch (dist_field) { - case RTE_ETH_RSS_L2_PAYLOAD: - case RTE_ETH_RSS_ETH: - if (l2_configured) - break; - l2_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_ETH; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_ETH_TYPE; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_PPPOE: - if (pppoe_configured) - break; - pppoe_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_PPPOE; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_PPPOE_SID; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_ESP: - if (esp_configured) - break; - esp_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IPSEC_ESP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IPSEC_ESP_SPI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_AH: - if (ah_configured) - break; - ah_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IPSEC_AH; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IPSEC_AH_SPI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_C_VLAN: - case RTE_ETH_RSS_S_VLAN: - if (vlan_configured) - break; - vlan_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_VLAN; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_VLAN_TCI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_MPLS: - - if (mpls_configured) - break; - mpls_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_1; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_2; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_N; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_IPV4: - case RTE_ETH_RSS_FRAG_IPV4: - case RTE_ETH_RSS_NONFRAG_IPV4_OTHER: - case RTE_ETH_RSS_IPV6: - case RTE_ETH_RSS_FRAG_IPV6: - case RTE_ETH_RSS_NONFRAG_IPV6_OTHER: - case RTE_ETH_RSS_IPV6_EX: - - if (l3_configured) - break; - l3_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IP_SRC; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IP_DST; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IP_PROTO; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_NONFRAG_IPV4_TCP: - case RTE_ETH_RSS_NONFRAG_IPV6_TCP: - case RTE_ETH_RSS_NONFRAG_IPV4_UDP: - case RTE_ETH_RSS_NONFRAG_IPV6_UDP: - case RTE_ETH_RSS_IPV6_TCP_EX: - case RTE_ETH_RSS_IPV6_UDP_EX: - case RTE_ETH_RSS_NONFRAG_IPV4_SCTP: - case RTE_ETH_RSS_NONFRAG_IPV6_SCTP: - - if (l4_configured) - break; - l4_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_TCP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_TCP_PORT_SRC; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_TCP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_TCP_PORT_DST; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - default: - DPAA2_PMD_WARN( - "unsupported flow dist option 0x%" PRIx64, - dist_field); - return -EINVAL; - } - } - req_dist_set = req_dist_set >> 1; - loop++; - } - kg_cfg->num_extracts = i; - return 0; -} - -int -dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, - struct fsl_mc_io *dpni, void *blist) -{ - /* Function to attach a DPNI with a buffer pool list. Buffer pool list - * handle is passed in blist. - */ - int32_t retcode; - struct dpni_pools_cfg bpool_cfg; - struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist; - struct dpni_buffer_layout layout; - int tot_size; - - /* ... rx buffer layout . - * Check alignment for buffer layouts first - */ - - /* ... rx buffer layout ... */ - if (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) { - int out_min_hdr_room, in_min_hdr_room; - /** Additional headroom layout for IPSec with TX configure - * dynamic enabled. - */ - in_min_hdr_room = DPAA2_RX_MIN_FD_OFFSET + - DPAA2_SEC_SIMPLE_FD_IB_MIN; - out_min_hdr_room = DPAA2_DYN_TX_MIN_FD_OFFSET + - DPAA2_SEC_SIMPLE_FD_OB_MIN; - tot_size = RTE_MAX(in_min_hdr_room, out_min_hdr_room); - if (tot_size < RTE_PKTMBUF_HEADROOM) - tot_size = RTE_PKTMBUF_HEADROOM; - } else { - tot_size = RTE_PKTMBUF_HEADROOM; - } - tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN); - - memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | - DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | - DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | - DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | - DPNI_BUF_LAYOUT_OPT_TIMESTAMP | - DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; - - layout.pass_timestamp = true; - layout.pass_frame_status = 1; - layout.private_data_size = DPAA2_FD_PTA_SIZE; - layout.pass_parser_result = 1; - layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN; - layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - - DPAA2_MBUF_HW_ANNOTATION; - retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX, &layout); - if (retcode) { - DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)", - retcode); - return retcode; - } - - /*Attach buffer pool to the network interface as described by the user*/ - memset(&bpool_cfg, 0, sizeof(struct dpni_pools_cfg)); - bpool_cfg.num_dpbp = 1; - bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; - bpool_cfg.pools[0].backup_pool = 0; - bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size, - DPAA2_PACKET_LAYOUT_ALIGN); - bpool_cfg.pools[0].priority_mask = 0; - - retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg); - if (retcode != 0) { - DPAA2_PMD_ERR("Error configuring buffer pool on interface." - " bpid = %d error code = %d", - bpool_cfg.pools[0].dpbp_id, retcode); - return retcode; - } - - priv->bp_list = bp_list; - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 1836226706..a7c9bb678e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -73,8 +73,6 @@ static uint64_t dev_tx_offloads_sup = static uint64_t dev_tx_offloads_nodis = RTE_ETH_TX_OFFLOAD_MULTI_SEGS; -bool dpaa2_print_parser_result; - /* Rx descriptor limit when DPNI loads PFDRs in PEB */ #define MAX_NB_RX_DESC_IN_PEB 11264 static int total_nb_rx_desc; @@ -85,27 +83,6 @@ static int total_nb_rx_desc; * patterns are inspected by dpaa2_dev_rss_reta_update(). */ #define DPAA2_RETA_SIZE 64 - -/* Values of dist_size accepted by the DPNI 'dpni_set_rx_hash_dist' MC command. - * Source: fsl_dpni.h, "struct dpni_rx_dist_cfg::dist_size" documentation. - * Used by dpaa2_dev_rss_reta_update() to validate user-requested patterns. - */ -static const uint16_t dpaa2_dist_size_allowed[] = { - 1, 2, 3, 4, 6, 7, 8, 12, 14, 16, 24, 28, 32, 48, 56, 64, - 96, 112, 128, 192, 224, 256, 384, 448, 512, 768, 896, 1024, -}; - -static bool -dpaa2_dist_size_is_supported(uint16_t n) -{ - size_t i; - for (i = 0; i < RTE_DIM(dpaa2_dist_size_allowed); i++) { - if (dpaa2_dist_size_allowed[i] == n) - return true; - } - return false; -} - int dpaa2_valid_dev; struct rte_mempool *dpaa2_tx_sg_pool; @@ -396,6 +373,197 @@ static int dpaa2_dev_link_update(struct rte_eth_dev *dev, static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev); static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev); static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); +static int +dpaa2_setup_table_miss_action(struct rte_eth_dev *eth_dev, + uint8_t tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct rte_flow_group_attr attr; + struct rte_flow_action actions[2]; + struct dpaa2_flow_tbl_profile *tbl_profile; + + memset(&attr, 0, sizeof(attr)); + attr.ingress = 1; + if (tc_index < priv->num_rx_tc) { + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (tbl_profile->default_drop) { + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else if (tbl_profile->default_queue.index >= eth_dev->data->nb_rx_queues) { + DPAA2_PMD_DEBUG("%s-tc%d-default-rxq(%d) >= max rxq(%d), Force to drop.", + eth_dev->data->name, tc_index, tbl_profile->default_queue.index, + eth_dev->data->nb_rx_queues); + tbl_profile->default_drop = true; + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else { + actions[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; + actions[0].conf = &tbl_profile->default_queue; + } + } else { + tbl_profile = &priv->flow_profile.qos_profile; + if (tbl_profile->default_drop) { + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else if (tbl_profile->default_jump.group >= priv->num_rx_tc) { + DPAA2_PMD_DEBUG("%s-default-tc(%d) >= max tc(%d), Force to drop.", + eth_dev->data->name, tbl_profile->default_jump.group, + priv->num_rx_tc); + tbl_profile->default_drop = true; + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else { + actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + actions[0].conf = &tbl_profile->default_jump; + } + } + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + + return rte_flow_group_set_miss_actions(eth_dev->data->port_id, + tc_index, &attr, actions, NULL); +} + +static int +dpaa2_setup_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint64_t req_dist_set, int tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + int tc_dist_queues; + struct rte_flow_attr attr; + struct rte_flow_action_rss action_rss; + struct rte_flow_action actions[2]; + struct rte_flow *rss_flow; + + /*TC distribution size is set with dist_queues or + * nb_rx_queues % dist_queues in order of TC priority index. + * Calculating dist size for this tc_index:- + */ + tc_dist_queues = eth_dev->data->nb_rx_queues - + tc_index * priv->dist_queues; + if (tc_dist_queues <= 0) { + DPAA2_PMD_DEBUG("No distribution on TC%d", tc_index); + return 0; + } + + if (tc_dist_queues > priv->dist_queues) + tc_dist_queues = priv->dist_queues; + + memset(&attr, 0, sizeof(attr)); + action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT; + action_rss.level = 0; + action_rss.types = req_dist_set; + action_rss.key_len = 0; + action_rss.key = NULL; + action_rss.queue = NULL; + action_rss.queue_num = tc_dist_queues; + + actions[0].type = RTE_FLOW_ACTION_TYPE_RSS; + actions[0].conf = &action_rss; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + attr.group = tc_index; + attr.ingress = 1; + rss_flow = rte_flow_create(eth_dev->data->port_id, &attr, NULL, actions, NULL); + if (!rss_flow) { + DPAA2_PMD_WARN("%s: Set RSS flow dist on tc%d failed", + __func__, tc_index); + return -EIO; + } + + return 0; +} + +static int +dpaa2_setup_flow_dcb_dist(struct rte_eth_dev *eth_dev, + uint8_t prio, uint8_t tc) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct rte_flow_attr attr; + struct rte_flow_action actions[2]; + struct rte_flow_item_vlan vlan_item; + struct rte_flow_item_vlan vlan_mask; + struct rte_flow_item items[2]; + struct rte_flow_action_jump action_jump; + struct rte_flow *qos_flow; + + memset(&attr, 0, sizeof(struct rte_flow_attr)); + attr.ingress = 1; + + attr.group = priv->num_rx_tc; + attr.priority = prio; + memset(&vlan_item, 0, sizeof(struct rte_flow_item_vlan)); + memset(&vlan_mask, 0, sizeof(struct rte_flow_item_vlan)); + vlan_item.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_TCI_MAKE(0, prio, 0)); + vlan_mask.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_PRI_MASK); + items[0].spec = &vlan_item; + items[0].mask = &vlan_mask; + items[0].type = RTE_FLOW_ITEM_TYPE_VLAN; + items[1].type = RTE_FLOW_ITEM_TYPE_END; + + actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + action_jump.group = tc; + actions[0].conf = &action_jump; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + + qos_flow = rte_flow_create(eth_dev->data->port_id, + &attr, items, actions, NULL); + if (!qos_flow) { + DPAA2_PMD_WARN("Failed to direct vlan with prio(%d) to tc%d", prio, tc); + return -EIO; + } + priv->dcb_flow[prio] = qos_flow; + + return 0; +} + +static int +dpaa2_remove_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint8_t tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile; + int ret; + + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (!tbl_profile->rss_flow || !tbl_profile->is_rss) { + DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed", + eth_dev->data->name, tc_index); + return 0; + } + ret = rte_flow_destroy(eth_dev->data->port_id, tbl_profile->rss_flow, NULL); + if (ret) + return ret; + tbl_profile->rss_flow = NULL; + + return 0; +} + +static int +dpaa2_update_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint64_t req_dist_set, int tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct rte_flow_action_rss action_rss; + struct rte_flow_action actions[2]; + int ret; + + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (!tbl_profile->rss_flow || !tbl_profile->is_rss) { + DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed", + eth_dev->data->name, tc_index); + return 0; + } + action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT; + action_rss.level = 0; + action_rss.types = req_dist_set; + action_rss.key_len = 0; + action_rss.queue_num = tbl_profile->tc_cfg.dist_size; + action_rss.key = NULL; + action_rss.queue = NULL; + actions[0].type = RTE_FLOW_ACTION_TYPE_RSS; + actions[0].conf = &action_rss; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + ret = rte_flow_actions_update(eth_dev->data->port_id, tbl_profile->rss_flow, + actions, NULL); + + return ret; +} static int dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) @@ -613,7 +781,7 @@ dpaa2_dev_info_get(struct rte_eth_dev *dev, dev_rx_offloads_nodis; dev_info->tx_offload_capa = dev_tx_offloads_sup | dev_tx_offloads_nodis; - dev_info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP; + dev_info->dev_capa = 0; dev_info->max_hash_mac_addrs = 0; dev_info->max_vfs = 0; @@ -883,6 +1051,28 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) } } +static int +dpaa2_dev_dcb_info(struct rte_eth_dev *dev, + struct rte_eth_dcb_info *dcb_info) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int i; + + if (!priv->nb_dcb_tcs) + return -ENOTSUP; + + memset(dcb_info, 0, sizeof(struct rte_eth_dcb_info)); + dcb_info->nb_tcs = priv->nb_dcb_tcs; + rte_memcpy(dcb_info->prio_tc, priv->prio_dcb_tc, + sizeof(uint8_t) * RTE_ETH_DCB_NUM_USER_PRIORITIES); + for (i = 0; i < dcb_info->nb_tcs; i++) { + dcb_info->tc_queue.tc_rxq[0][i].base = priv->dist_queues * i; + dcb_info->tc_queue.tc_rxq[0][i].nb_queue = priv->dist_queues; + } + + return 0; +} + static int dpaa2_eth_dev_configure(struct rte_eth_dev *dev) { @@ -895,8 +1085,12 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) int rx_l4_csum_offload = false; int tx_l3_csum_offload = false; int tx_l4_csum_offload = false; - int ret, tc_index; - uint32_t max_rx_pktlen; + int ret, tc_index, nb_tcs; + uint32_t max_rx_pktlen, base; + struct rte_eth_rss_conf *rss_conf; + struct rte_eth_dcb_rx_conf *dcb_rx_conf; + struct rte_dpaa2_default_action_conf *def_act_conf; + struct dpaa2_flow_tbl_profile *tbl_profile; PMD_INIT_FUNC_TRACE(); @@ -942,15 +1136,64 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) return -1; } - if (eth_conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) { + rss_conf = ð_conf->rx_adv_conf.rss_conf; + dcb_rx_conf = ð_conf->rx_adv_conf.dcb_rx_conf; + def_act_conf = eth_conf->rxmode.reserved_ptrs[0]; + + for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + base = priv->dist_queues * tc_index; + if (def_act_conf && tc_index < def_act_conf->max_tc) { + if (def_act_conf->default_flows[tc_index] >= priv->dist_queues) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_queue.index = base + + def_act_conf->default_flows[tc_index]; + } + } + if (priv->fs_entries) { + ret = dpaa2_setup_table_miss_action(dev, tc_index); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-tc%d table", + ret, dev->data->name, tc_index); + } + } + } + if (def_act_conf) { + tbl_profile = &priv->flow_profile.qos_profile; + if (def_act_conf->default_tc >= priv->num_rx_tc) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_jump.group = def_act_conf->default_tc; + } + } + ret = dpaa2_setup_table_miss_action(dev, priv->num_rx_tc); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-QoS table", + ret, dev->data->name); + } + + if (eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist(dev, - eth_conf->rx_adv_conf.rss_conf.rss_hf, - tc_index); + ret = dpaa2_setup_flow_rss_dist(dev, rss_conf->rss_hf, tc_index); if (ret) { - DPAA2_PMD_ERR( - "Unable to set flow distribution on tc%d." - "Check queue config", tc_index); + DPAA2_PMD_ERR("RSS dist on tc%d err(%d)", tc_index, ret); + return ret; + } + } + } + + if ((eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_DCB) && priv->qos_entries) { + nb_tcs = dcb_rx_conf->nb_tcs; + for (tc_index = 0; tc_index < nb_tcs; tc_index++) { + if (tc_index >= priv->num_rx_tc) + break; + ret = dpaa2_setup_flow_dcb_dist(dev, dcb_rx_conf->dcb_tc[tc_index], + tc_index); + if (ret) { + DPAA2_PMD_ERR("DCB direct to tc%d err(%d)", tc_index, ret); return ret; } } @@ -1097,7 +1340,6 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, struct dpni_taildrop taildrop; uint8_t qopt = 0; uint16_t flow_id; - uint32_t bpid; int ret; PMD_INIT_FUNC_TRACE(); @@ -1116,18 +1358,6 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, nb_rx_desc); } - if (!priv->bp_list || priv->bp_list->mp != mb_pool) { - if (rte_eal_process_type() != RTE_PROC_PRIMARY) { - ret = rte_dpaa2_bpid_info_init(mb_pool); - if (ret) - return ret; - } - bpid = mempool_to_bpid(mb_pool); - ret = dpaa2_attach_bp_list(priv, dpni, - rte_dpaa2_bpid_info[bpid].bp_list); - if (ret) - return ret; - } dpaa2_q = priv->rx_vq[rx_queue_id]; if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", @@ -1797,6 +2027,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) struct fsl_mc_io *dpni = dev->process_private; int i, ret; struct rte_eth_link link; + struct dpaa2_flow_tbl_profile *tbl_profile; PMD_INIT_FUNC_TRACE(); @@ -1809,7 +2040,9 @@ dpaa2_dev_close(struct rte_eth_dev *dev) } dpaa2_tm_deinit(dev); - dpaa2_flow_clean(dev); + dpaa2_flow_clean(dev, MAX_TCS); + /** No matter dcb flows are created or not, they are destroyed in flow clean.*/ + memset(priv->dcb_flow, 0, sizeof(void *) * RTE_ETH_DCB_NUM_USER_PRIORITIES); /* Clean the device first */ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); if (ret) { @@ -1843,10 +2076,16 @@ dpaa2_dev_close(struct rte_eth_dev *dev) dev->process_private = NULL; rte_free(dpni); - for (i = 0; i < MAX_TCS; i++) - rte_free(priv->extract.tc_extract_param[i]); - - rte_free(priv->extract.qos_extract_param); + for (i = 0; i < (MAX_TCS + 1); i++) { + if (i < MAX_TCS) + tbl_profile = &priv->flow_profile.tc_profile[i]; + else + tbl_profile = &priv->flow_profile.qos_profile; + rte_free(tbl_profile->extract_param); + tbl_profile->extract_param = NULL; + rte_free(tbl_profile->entry_map); + tbl_profile->entry_map = NULL; + } rte_free(priv->cnt_idx_dma_mem); rte_free(priv->cnt_values_dma_mem); @@ -2746,25 +2985,25 @@ dpaa2_dev_rss_hash_update(struct rte_eth_dev *dev, if (rss_conf->rss_hf) { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist(dev, rss_conf->rss_hf, + ret = dpaa2_update_flow_rss_dist(dev, rss_conf->rss_hf, tc_index); - if (ret) { - DPAA2_PMD_ERR("Unable to set flow dist on tc%d", - tc_index); - return ret; - } + if (ret) + break; } } else { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_remove_flow_dist(dev, tc_index); - if (ret) { - DPAA2_PMD_ERR( - "Unable to remove flow dist on tc%d", - tc_index); - return ret; - } + ret = dpaa2_remove_flow_rss_dist(dev, tc_index); + if (ret) + break; } } + if (ret) { + DPAA2_PMD_ERR("%s: %s flow dist on tc%d err(%d)", + data->name, rss_conf->rss_hf ? "set" : "remove", + tc_index, ret); + + return ret; + } eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_conf->rss_hf; return 0; } @@ -2879,23 +3118,34 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, } } - if (!dpaa2_dist_size_is_supported(n)) { - DPAA2_PMD_ERR("dist_size %u not supported by HW. Allowed: " - "1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,...", - n); + /* The requested distribution size cannot exceed the number of + * distribution queues provisioned per TC. Any HW-specific limitation + * on the exact value is enforced later by the rte_flow update. + */ + if (n > priv->dist_queues) { + DPAA2_PMD_ERR("dist_size %u exceeds max distribution queues %u", + n, priv->dist_queues); return -ENOTSUP; } - /* Apply on every configured RX TC, matching rss_hash_update behavior. */ + /* Apply on every configured RX TC, matching rss_hash_update behavior. + * Program the new dist_size into each TC's RSS flow profile and push + * it to the live flow via rte_flow_actions_update(). + */ for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist_size(dev, + struct dpaa2_flow_tbl_profile *tbl_profile = + &priv->flow_profile.tc_profile[tc_index]; + + tbl_profile->tc_cfg.dist_size = n; + ret = dpaa2_update_flow_rss_dist(dev, eth_conf->rx_adv_conf.rss_conf.rss_hf, - tc_index, n); + tc_index); if (ret) { DPAA2_PMD_ERR("Failed to apply dist_size=%u on tc%d (err=%d)", n, tc_index, ret); return ret; } + priv->dist_size_cur[tc_index] = n; } DPAA2_PMD_DEBUG("RETA updated: dist_size now %u on %u TC(s)", @@ -3453,7 +3703,8 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .timesync_adjust_time = dpaa2_timesync_adjust_time, .timesync_read_rx_timestamp = dpaa2_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = dpaa2_timesync_read_tx_timestamp, - .mtr_ops_get = dpaa2_mtr_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, + .get_dcb_info = dpaa2_dev_dcb_info }; /* Populate the mac address from physically available (u-boot/firmware) and/or @@ -3570,7 +3821,9 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) struct dpni_attr attr; struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; struct dpni_buffer_layout layout; - int ret, hw_id, i; + int ret, hw_id, i, entry_num; + struct dpaa2_flow_tbl_profile *tbl_profile; + uint64_t iova; PMD_INIT_FUNC_TRACE(); @@ -3668,8 +3921,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; - priv->default_flow = RTE_MIN(priv->fs_entries, - priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ @@ -3830,27 +4081,51 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) eth_dev->tx_pkt_burst = dpaa2_dev_tx; /* Init fields w.r.t. classification */ - memset(&priv->extract.qos_key_extract, 0, - sizeof(struct dpaa2_key_extract)); - priv->extract.qos_extract_param = rte_zmalloc(NULL, - DPAA2_EXTRACT_PARAM_MAX_SIZE, - RTE_CACHE_LINE_SIZE); - if (!priv->extract.qos_extract_param) { - DPAA2_PMD_ERR("Memory alloc failed"); - goto init_err; - } - - for (i = 0; i < MAX_TCS; i++) { - memset(&priv->extract.tc_key_extract[i], 0, - sizeof(struct dpaa2_key_extract)); - priv->extract.tc_extract_param[i] = rte_zmalloc(NULL, + for (i = 0; i < (MAX_TCS + 1); i++) { + if (i < MAX_TCS) { + tbl_profile = &priv->flow_profile.tc_profile[i]; + entry_num = priv->fs_entries; + } else { + tbl_profile = &priv->flow_profile.qos_profile; + entry_num = priv->qos_entries; + } + memset(tbl_profile, 0, sizeof(struct dpaa2_flow_tbl_profile)); + tbl_profile->extract_param = rte_zmalloc(NULL, DPAA2_EXTRACT_PARAM_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!priv->extract.tc_extract_param[i]) { - DPAA2_PMD_ERR("Memory alloc failed"); + if (!tbl_profile->extract_param) goto init_err; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(tbl_profile->extract_param, + DPAA2_EXTRACT_PARAM_MAX_SIZE); + tbl_profile->default_drop = false; + if (i < MAX_TCS) { + tbl_profile->tc_cfg.dist_size = priv->dist_queues; + tbl_profile->tc_cfg.key_cfg_iova = iova; + tbl_profile->tc_cfg.tc = i; + /** First flow of TC as default flow, otherwise, may be dropped.*/ + tbl_profile->default_queue.index = priv->dist_queues * i; + } else { + tbl_profile->qos_cfg.key_cfg_iova = iova; + tbl_profile->qos_cfg.keep_entries = true; + /** First TC as default TC, otherwise, may be dropped.*/ + tbl_profile->default_jump.group = 0; } + if (!entry_num) + continue; + + tbl_profile->entry_map = rte_zmalloc(NULL, entry_num / 8 + 1, 0); + if (!tbl_profile->entry_map) + goto init_err; + } + + for (i = 0; i < priv->num_rx_tc; i++) { + if (i >= RTE_ETH_DCB_NUM_USER_PRIORITIES) + break; + if (i >= priv->qos_entries) + break; + priv->prio_dcb_tc[i] = i; } + priv->nb_dcb_tcs = i; ret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token, RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 523c420c51..5659abcd51 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ @@ -12,6 +12,7 @@ #include <rte_compat.h> #include <rte_event_eth_rx_adapter.h> #include <rte_pmd_dpaa2.h> +#include <rte_string_fns.h> #include <bus_fslmc_driver.h> #include <dpaa2_hw_pvt.h> @@ -24,6 +25,13 @@ #include "base/dpaa2_hw_dpni_annot.h" #include "dpaa2_parser_decode.h" +#define DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 106) +#define DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV RTE_FSL_MC_REV(10, 39, 106) +#define DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_POLICER_SET_V2_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV DPAA2_POLICER_SET_V2_MC_REV +#define DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV RTE_FSL_MC_REV(10, 39, 109) #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -35,6 +43,10 @@ #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 +#define DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv) \ + container_of((((struct dpaa2_dev_priv *)priv)->eth_dev->device), \ + struct rte_dpaa2_device, device) + #define DPAA2_EXTRACT_PARAM_MAX_SIZE \ RTE_ALIGN(sizeof(struct dpni_ext_set_rx_tc_dist), 256) @@ -254,125 +266,9 @@ struct dpaa2_dyn_rx_protocol_pos { #define DPAA2_FS_FLC_FLOW_OFFSET \ (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) -#define DPAA2_FAPR_SIZE \ - (sizeof(struct dpaa2_annot_hdr) - \ - offsetof(struct dpaa2_annot_hdr, word3)) - -#define DPAA2_PR_NXTHDR_OFFSET 0 - -#define DPAA2_FAFE_PSR_OFFSET 2 -#define DPAA2_FAFE_PSR_SIZE 2 - -#define DPAA2_FAF_PSR_OFFSET 4 -#define DPAA2_FAF_PSR_SIZE 12 - -#define DPAA2_FAF_TOTAL_SIZE \ - (DPAA2_FAFE_PSR_SIZE + DPAA2_FAF_PSR_SIZE) - -/* Just most popular Frame attribute flags (FAF) here.*/ -enum dpaa2_rx_faf_offset { - /* Set by SP start*/ - FAFE_VXLAN_IN_VLAN_FRAM = 0, - FAFE_VXLAN_IN_IPV4_FRAM = 1, - FAFE_VXLAN_IN_IPV6_FRAM = 2, - FAFE_VXLAN_IN_UDP_FRAM = 3, - FAFE_VXLAN_IN_TCP_FRAM = 4, - - FAFE_ECPRI_FRAM = 7, - /* Set by SP end*/ - - FAF_GTP_PRIMED_FRAM = 1 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_PTP_FRAM = 3 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_VXLAN_FRAM = 4 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ETH_FRAM = 10 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_LLC_SNAP_FRAM = 18 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_VLAN_FRAM = 21 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_PPPOE_PPP_FRAM = 25 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_MPLS_FRAM = 27 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ARP_FRAM = 30 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPV4_FRAM = 34 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPV6_FRAM = 42 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IP_FRAM = 48 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IP_FRAG_FRAM = 50 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ICMP_FRAM = 57 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IGMP_FRAM = 58 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_GRE_FRAM = 65 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_UDP_FRAM = 70 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_TCP_FRAM = 72 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_FRAM = 77 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_ESP_FRAM = 78 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_AH_FRAM = 79 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_SCTP_FRAM = 81 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_DCCP_FRAM = 83 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_GTP_FRAM = 87 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ESP_FRAM = 89 + DPAA2_FAFE_PSR_SIZE * 8, -}; - -enum dpaa2_ecpri_fafe_type { - ECPRI_FAFE_TYPE_0 = (8 - FAFE_ECPRI_FRAM), - ECPRI_FAFE_TYPE_1 = (8 - FAFE_ECPRI_FRAM) | (1 << 1), - ECPRI_FAFE_TYPE_2 = (8 - FAFE_ECPRI_FRAM) | (2 << 1), - ECPRI_FAFE_TYPE_3 = (8 - FAFE_ECPRI_FRAM) | (3 << 1), - ECPRI_FAFE_TYPE_4 = (8 - FAFE_ECPRI_FRAM) | (4 << 1), - ECPRI_FAFE_TYPE_5 = (8 - FAFE_ECPRI_FRAM) | (5 << 1), - ECPRI_FAFE_TYPE_6 = (8 - FAFE_ECPRI_FRAM) | (6 << 1), - ECPRI_FAFE_TYPE_7 = (8 - FAFE_ECPRI_FRAM) | (7 << 1) -}; - -#define DPAA2_PR_ETH_OFF_OFFSET 19 -#define DPAA2_PR_TCI_OFF_OFFSET 21 -#define DPAA2_PR_LAST_ETYPE_OFFSET 23 -#define DPAA2_PR_L3_OFF_OFFSET 27 -#define DPAA2_PR_L4_OFF_OFFSET 30 -#define DPAA2_PR_L5_OFF_OFFSET 31 -#define DPAA2_PR_NXTHDR_OFF_OFFSET 34 - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 -struct ipv4_sd_addr_extract_rule { - uint32_t ipv4_src; - uint32_t ipv4_dst; -}; - -struct ipv6_sd_addr_extract_rule { - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; -}; - -struct ipv4_ds_addr_extract_rule { - uint32_t ipv4_dst; - uint32_t ipv4_src; -}; - -struct ipv6_ds_addr_extract_rule { - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; -}; - -union ip_addr_extract_rule { - struct ipv4_sd_addr_extract_rule ipv4_sd_addr; - struct ipv6_sd_addr_extract_rule ipv6_sd_addr; - struct ipv4_ds_addr_extract_rule ipv4_ds_addr; - struct ipv6_ds_addr_extract_rule ipv6_ds_addr; -}; - -union ip_src_addr_extract_rule { - uint32_t ipv4_src; - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; -}; - -union ip_dst_addr_extract_rule { - uint32_t ipv4_dst; - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; -}; - -enum ip_addr_extract_type { - IP_NONE_ADDR_EXTRACT, - IP_SRC_EXTRACT, - IP_DST_EXTRACT, - IP_SRC_DST_EXTRACT, - IP_DST_SRC_EXTRACT -}; +#define DPAA2_IBTH_MAX_EXTRACT_NB 4 enum key_prot_type { /* HW extracts from standard protocol fields*/ @@ -389,9 +285,9 @@ struct key_prot_field { uint32_t key_field; }; -struct dpaa2_raw_region { - uint8_t raw_start; - uint8_t raw_size; +struct dpaa2_ip_addr_extract { + uint32_t field; + uint8_t max_size; }; struct dpaa2_key_profile { @@ -399,35 +295,52 @@ struct dpaa2_key_profile { uint8_t key_offset[DPKG_MAX_NUM_OF_EXTRACTS]; uint8_t key_size[DPKG_MAX_NUM_OF_EXTRACTS]; - enum ip_addr_extract_type ip_addr_type; - uint8_t ip_addr_extract_pos; - uint8_t ip_addr_extract_off; - - uint8_t raw_extract_pos; - uint8_t raw_extract_off; - uint8_t raw_extract_num; + struct dpaa2_ip_addr_extract ip_addr_extracts[2]; - uint8_t l4_src_port_present; - uint8_t l4_src_port_pos; - uint8_t l4_src_port_offset; - uint8_t l4_dst_port_present; - uint8_t l4_dst_port_pos; - uint8_t l4_dst_port_offset; + uint8_t l4_sp_present; + uint8_t l4_sp_extract_idx; + uint8_t l4_sp_key_offset; + uint8_t l4_dp_present; + uint8_t l4_dp_extract_idx; + uint8_t l4_dp_key_offset; struct key_prot_field prot_field[DPKG_MAX_NUM_OF_EXTRACTS]; uint16_t key_max_size; - struct dpaa2_raw_region raw_region; }; -struct dpaa2_key_extract { +struct dpaa2_flow_tbl_profile { struct dpkg_profile_cfg dpkg; struct dpaa2_key_profile key_profile; + uint8_t *extract_param; + int entry_num; + uint8_t *entry_map; + int enabled; + int is_rss; + void *rss_flow; + union { + struct dpni_qos_tbl_cfg qos_cfg; + struct dpni_rx_dist_cfg tc_cfg; + }; + int default_drop; + union { + struct rte_flow_action_jump default_jump; + struct rte_flow_action_queue default_queue; + }; }; -struct extract_s { - struct dpaa2_key_extract qos_key_extract; - struct dpaa2_key_extract tc_key_extract[MAX_TCS]; - uint8_t *qos_extract_param; - uint8_t *tc_extract_param[MAX_TCS]; +struct dpaa2_flow_profile { + struct dpaa2_flow_tbl_profile qos_profile; + struct dpaa2_flow_tbl_profile tc_profile[MAX_TCS]; + /** Meter per TC.*/ + struct dpaa2_dev_meter_profile *tc_mtr_profile[MAX_TCS]; + void *mtr_flow[MAX_TCS]; + void *mempool[MAX_TCS]; + uint8_t bp_idx[MAX_TCS]; +}; + +struct rte_dpaa2_default_action_conf { + uint8_t default_tc; + uint8_t max_tc; + uint16_t default_flows[]; }; struct dpaa2_dev_meter_profile { @@ -491,15 +404,12 @@ struct dpaa2_dev_priv { /** RXQs in same TC share same cgid.*/ uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; - /* Lowest priority FS flow id to receive flow steering miss frames. */ - uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. * Zero means "use default" (= nb_rx_queues clamped to dist_queues). */ uint16_t dist_size_cur[MAX_TCS]; - uint16_t dpni_ver_major; uint16_t dpni_ver_minor; uint32_t speed_capa; @@ -508,7 +418,10 @@ struct dpaa2_dev_priv { uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */ char ep_name[RTE_DEV_NAME_MAX_LEN]; - struct extract_s extract; + struct dpaa2_flow_profile flow_profile; + uint8_t nb_dcb_tcs; + uint8_t prio_dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES]; + void *dcb_flow[RTE_ETH_DCB_NUM_USER_PRIORITIES]; uint16_t ss_offset; uint64_t ss_iova; @@ -528,6 +441,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool enable_bp_flow_ctrl; bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ @@ -549,7 +463,7 @@ struct dpaa2_dev_priv { struct rte_mempool *tx_sg_pool; - struct dpaa2_dev_flow *curr; + struct dpaa2_generic_flow *cur_flow; LIST_HEAD(, dpaa2_dev_flow) flows; LIST_HEAD(, dpaa2_dev_meter_profile) profiles; LIST_HEAD(, dpaa2_dev_meter_policy) policies; @@ -569,6 +483,8 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +#define DPAA2_FLOW_DUMP dpaa2_dump_print + static inline void dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd, const struct rte_mbuf *m) @@ -619,21 +535,269 @@ dpaa2_timestamp_debug(struct dpaa2_dev_priv *priv, prefix, timestamp, (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec); } -int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg); +static inline void +dpaa2_prot_field_string(uint32_t prot, uint32_t field, + char *string, size_t size) +{ + if (prot == NET_PROT_ETH) { + strlcpy(string, "eth", size); + if (field == NH_FLD_ETH_DA) + strlcat(string, ".dst", size); + else if (field == NH_FLD_ETH_SA) + strlcat(string, ".src", size); + else if (field == NH_FLD_ETH_TYPE) + strlcat(string, ".type", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_VLAN) { + strlcpy(string, "vlan", size); + if (field == NH_FLD_VLAN_TCI) + strlcat(string, ".tci", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_IP) { + strlcpy(string, "ip", size); + if (field == NH_FLD_IP_SRC) + strlcat(string, ".src", size); + else if (field == NH_FLD_IP_DST) + strlcat(string, ".dst", size); + else if (field == NH_FLD_IP_PROTO) + strlcat(string, ".proto", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_TCP) { + strlcpy(string, "tcp", size); + if (field == NH_FLD_TCP_PORT_SRC) + strlcat(string, ".src", size); + else if (field == NH_FLD_TCP_PORT_DST) + strlcat(string, ".dst", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_UDP) { + strlcpy(string, "udp", size); + if (field == NH_FLD_UDP_PORT_SRC) + strlcat(string, ".src", size); + else if (field == NH_FLD_UDP_PORT_DST) + strlcat(string, ".dst", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_ICMP) { + strlcpy(string, "icmp", size); + if (field == NH_FLD_ICMP_TYPE) + strlcat(string, ".type", size); + else if (field == NH_FLD_ICMP_CODE) + strlcat(string, ".code", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_SCTP) { + strlcpy(string, "sctp", size); + if (field == NH_FLD_SCTP_PORT_SRC) + strlcat(string, ".src", size); + else if (field == NH_FLD_SCTP_PORT_DST) + strlcat(string, ".dst", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_GRE) { + strlcpy(string, "gre", size); + if (field == NH_FLD_GRE_TYPE) + strlcat(string, ".type", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_GTP) { + strlcpy(string, "gtp", size); + if (field == NH_FLD_GTP_TEID) + strlcat(string, ".teid", size); + else + strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_IPSEC_ESP) { + strlcpy(string, "esp", size); + if (field == NH_FLD_IPSEC_ESP_SPI) + strlcat(string, ".spi", size); + else if (field == NH_FLD_IPSEC_ESP_SEQUENCE_NUM) + strlcat(string, ".seq", size); + else + strlcat(string, ".unknown field", size); + } else { + snprintf(string, size, "unknown protocol(%d)", prot); + } +} + +static inline void +dpaa2_dump_dpkg(const struct dpkg_profile_cfg *dpkg) +{ + int idx; + char string[32]; + const struct dpkg_extract *extract; + enum dpkg_extract_type type; + enum net_prot prot; + uint32_t field; + + for (idx = 0; idx < dpkg->num_extracts; idx++) { + extract = &dpkg->extracts[idx]; + type = extract->type; + if (type == DPKG_EXTRACT_FROM_HDR) { + prot = extract->extract.from_hdr.prot; + field = extract->extract.from_hdr.field; + dpaa2_prot_field_string(prot, field, string, sizeof(string)); + } else if (type == DPKG_EXTRACT_FROM_DATA) { + snprintf(string, sizeof(string), "raw offset/len: %d/%d", + extract->extract.from_data.offset, + extract->extract.from_data.size); + } else if (type == DPKG_EXTRACT_FROM_PARSE) { + snprintf(string, sizeof(string), "parse offset/len: %d/%d", + extract->extract.from_parse.offset, + extract->extract.from_parse.size); + } + DPAA2_FLOW_DUMP("%s", string); + if ((idx + 1) < dpkg->num_extracts) + DPAA2_FLOW_DUMP(" / "); + else + DPAA2_FLOW_DUMP("\r\n\n"); + } +} + +static inline int +dpaa2_extract_prev_ip_addr_pos(const struct dpaa2_key_profile *profile) +{ + int idx = -ENXIO; + + if (!profile->num) + return -ENXIO; + + for (idx = profile->num - 1; idx >= 0; idx--) { + if (!(profile->prot_field[idx].type == DPAA2_NET_PROT_KEY && + profile->prot_field[idx].prot == NET_PROT_IP && + (profile->prot_field[idx].key_field == NH_FLD_IP_SRC || + profile->prot_field[idx].key_field == NH_FLD_IP_DST))) + break; + } + + if (idx >= 0) + return idx; + return -ENXIO; +} + +static inline int +dpaa2_extract_ip_addr_add(uint32_t field, + struct dpaa2_key_profile *key_profile, uint8_t size, + int *update, int *pos) +{ + struct dpaa2_ip_addr_extract *ip_addr_extracts; + uint8_t i = 0; + uint16_t max_size_save = key_profile->key_max_size; + char log_buf[128]; + + if (field != NH_FLD_IP_SRC && field != NH_FLD_IP_DST) + return -EINVAL; + + max_size_save -= key_profile->ip_addr_extracts[0].max_size; + max_size_save -= key_profile->ip_addr_extracts[1].max_size; + ip_addr_extracts = key_profile->ip_addr_extracts; + while (i < 2) { + if (ip_addr_extracts[i].field == field) { + if (size > ip_addr_extracts[i].max_size) + ip_addr_extracts[i].max_size = size; + break; + } + if (!ip_addr_extracts[i].field) { + ip_addr_extracts[i].field = field; + ip_addr_extracts[i].max_size = size; + if (update) + *update = 1; + break; + } + i++; + } + if (i > 1) { + snprintf(log_buf, sizeof(log_buf), + "field[0](%d)/size[0](%d)/field[1](%d)/size[1](%d)", + ip_addr_extracts[0].field, + ip_addr_extracts[0].max_size, + ip_addr_extracts[1].field, + ip_addr_extracts[1].max_size); + DPAA2_FLOW_DUMP("Invalid IP address extracts:%s\n", + log_buf); + return -EINVAL; + } + + if (pos) + *pos = i; + + max_size_save += key_profile->ip_addr_extracts[0].max_size; + max_size_save += key_profile->ip_addr_extracts[1].max_size; + key_profile->key_max_size = max_size_save; + + return 0; +} + +static inline uint8_t +dpaa2_profile_insert_no_ipaddr_extract(struct dpaa2_key_profile *profile, + uint8_t size, uint8_t *poffset, int *ppos, + const struct key_prot_field *prot) +{ + uint8_t idx, ip_addr_num = 0, offset; + + if (profile->ip_addr_extracts[0].field && + profile->ip_addr_extracts[1].field) { + idx = profile->num - 2; + ip_addr_num = 2; + } else if (profile->ip_addr_extracts[0].field) { + idx = profile->num - 1; + ip_addr_num = 1; + } else { + idx = profile->num; + } -int dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index); + if (idx > 0) + offset = profile->key_offset[idx - 1] + profile->key_size[idx - 1]; + else + offset = 0; -int dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index, uint16_t dist_size); + if (idx > 0) { + profile->key_offset[idx] = + profile->key_offset[idx - 1] + profile->key_size[idx - 1]; + } else { + profile->key_offset[idx] = 0; + } + if (ppos) + *ppos = profile->key_offset[idx]; + profile->key_size[idx] = size; + profile->key_max_size += size; + profile->num++; + + if (ip_addr_num > 0) { + memmove(&profile->prot_field[idx + 1], + &profile->prot_field[idx], + sizeof(struct key_prot_field) * ip_addr_num); + } + if (poffset) + *poffset = offset; -int dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev, - uint8_t tc_index); + if (prot) { + rte_memcpy(&profile->prot_field[idx], prot, + sizeof(struct key_prot_field)); + } -int dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, - struct fsl_mc_io *dpni, void *blist); + return idx; +} + +static inline void +dpaa2_dpkg_insert_extract(struct dpkg_profile_cfg *kg_cfg, + int idx, const struct dpkg_extract *extract) +{ + int i; + if (idx != kg_cfg->num_extracts) { + /* Not the last extract index, must have IP address extract.*/ + for (i = kg_cfg->num_extracts - 1; i >= idx; i--) { + rte_memcpy(&kg_cfg->extracts[i + 1], + &kg_cfg->extracts[i], sizeof(struct dpkg_extract)); + } + } + + rte_memcpy(&kg_cfg->extracts[idx], extract, sizeof(struct dpkg_extract)); + kg_cfg->num_extracts++; +} __rte_internal int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, int eth_rx_queue_id, @@ -678,7 +842,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, struct rte_mbuf **bufs, uint16_t nb_pkts); void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); -void dpaa2_flow_clean(struct rte_eth_dev *dev); +void dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id); uint16_t dpaa2_dev_tx_conf(void *txq, int drain); void diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index c616857e98..8456b3b80d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2022 NXP + * Copyright 2018-2026 NXP */ #include <sys/queue.h> @@ -16,6 +16,7 @@ #include <rte_flow_driver.h> #include <rte_tailq.h> +#include <eal_export.h> #include <fsl_dpni.h> #include <fsl_dpkg.h> @@ -23,7 +24,28 @@ #include <dpaa2_pmd_logs.h> #include "dpaa2_parser_decode.h" -static char *dpaa2_flow_control_log; +#ifndef RTE_DPAA2_ONE_LEVEL_GROUP_FLOW +#define RTE_DPAA2_ONE_LEVEL_GROUP_FLOW 0 +#endif +#ifndef RTE_DPAA2_QOS_GROUP_FLOW +#define RTE_DPAA2_QOS_GROUP_FLOW 1 +#endif +#ifndef RTE_DPAA2_FS_GROUP_FLOW +#define RTE_DPAA2_FS_GROUP_FLOW 2 +#endif + +#ifndef RTE_DPAA2_FLOW_GROUP_TYPE_GET +#define RTE_DPAA2_FLOW_GROUP_TYPE_GET(group) \ + ((void)(group), RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) +#endif + +#ifndef RTE_DPAA2_FLOW_GROUP_ID_GET +#define RTE_DPAA2_FLOW_GROUP_ID_GET(group) (group) +#endif + +static bool dpaa2_flow_control_log; + +#define DPAA2_FLOW_QOS_GROUP_ID 0xff /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -34,31 +56,61 @@ enum dpaa2_flow_entry_size { }; enum dpaa2_flow_dist_type { - DPAA2_FLOW_QOS_TYPE = 1 << 0, - DPAA2_FLOW_FS_TYPE = 1 << 1 + DPAA2_FLOW_NULL_TYPE, + DPAA2_FLOW_QOS_TYPE, + DPAA2_FLOW_FS_TYPE }; #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 -#define DPAA2_PROT_FIELD_STRING_SIZE 16 + #define VXLAN_HF_VNI 0x08 +#define DPAA2_MAX_ACTION_PER_FLOW_NUM 4 -struct dpaa2_dev_flow { - LIST_ENTRY(dpaa2_dev_flow) next; - struct dpni_rule_cfg qos_rule; - uint8_t *qos_key_addr; - uint8_t *qos_mask_addr; - uint16_t qos_rule_size; - struct dpni_rule_cfg fs_rule; - uint8_t qos_real_key_size; - uint8_t fs_real_key_size; - uint8_t *fs_key_addr; - uint8_t *fs_mask_addr; - uint16_t fs_rule_size; - uint8_t tc_id; /** Traffic Class ID. */ - uint8_t tc_index; /** index within this Traffic Class. */ +struct dpaa2_dev_flow_qos_action { + enum rte_flow_action_type action_jump_type; + struct rte_flow_action_jump action_jump_cfg; +}; + +struct dpaa2_dev_flow_fs_action { enum rte_flow_action_type action_type; struct dpni_fs_action_cfg fs_action_cfg; + char dst_name[DPNI_FS_REDIR_MAX_NUM][RTE_ETH_NAME_MAX_LEN]; +}; + +union dpaa2_dev_flow_action { + struct dpaa2_dev_flow_qos_action qos_action; + struct dpaa2_dev_flow_fs_action fs_action; +}; + +struct dpaa2_generic_flow { + struct dpni_rule_cfg rule_cfg; + uint8_t *key_addr; + uint8_t *mask_addr; + uint16_t rule_size; + uint16_t entry_index; + /** This flow has IPv4 or IPv6 extracts.*/ + enum net_prot ip_key; + /** This flow has IPv4 or IPv6 source extract.*/ + enum net_prot ip_src; + /** This flow has IPv4 or IPv6 destination extract.*/ + enum net_prot ip_dst; + struct dpaa2_dev_priv *priv; + union { + uint8_t tc_id; /** For FS flow only.*/ + uint8_t flow_id; /** For QoS flow with direct_queue.*/ + }; + union dpaa2_dev_flow_action flow_action; + int is_rss; + int direct_queue; +}; + +struct dpaa2_dev_flow { + LIST_ENTRY(dpaa2_dev_flow) next; + struct dpaa2_generic_flow *qos_flow; + struct dpaa2_generic_flow *fs_flow; + struct dpaa2_dev_priv *priv; + int is_meter_flow; }; struct rte_dpaa2_flow_item { @@ -81,20 +133,18 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, - RTE_FLOW_ITEM_TYPE_MPLS, - RTE_FLOW_ITEM_TYPE_PPPOES, - RTE_FLOW_ITEM_TYPE_RAW + RTE_FLOW_ITEM_TYPE_RAW, + /** Hardware parser supports vlan protocol only.*/ + RTE_FLOW_ITEM_TYPE_VXLAN }; static const enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI + RTE_FLOW_ITEM_TYPE_ECPRI, + RTE_FLOW_ITEM_TYPE_GENEVE }; -static const -enum rte_flow_action_type dpaa2_supported_action_type[] = { - RTE_FLOW_ACTION_TYPE_END, +static const enum rte_flow_action_type dpaa2_supported_fs_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, @@ -102,27 +152,63 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_DROP }; +static const enum rte_flow_action_type dpaa2_supported_qos_action_type[] = { + RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_JUMP, + RTE_FLOW_ACTION_TYPE_DROP +}; + +static const enum rte_flow_action_type dpaa2_supported_meter_action_type[] = { + RTE_FLOW_ACTION_TYPE_METER_MARK, + RTE_FLOW_ACTION_TYPE_METER +}; + +#define DPAA2_FLOW_HDR_HEX_DUMP_SIZE \ + (RTE_MAX(sizeof(struct rte_flow_item_eth), \ + RTE_MAX(sizeof(struct rte_flow_item_vlan), \ + RTE_MAX(sizeof(struct rte_flow_item_ipv4), \ + RTE_MAX(sizeof(struct rte_flow_item_ipv6), \ + RTE_MAX(sizeof(struct rte_flow_item_icmp), \ + RTE_MAX(sizeof(struct rte_flow_item_udp), \ + RTE_MAX(sizeof(struct rte_flow_item_tcp), \ + RTE_MAX(sizeof(struct rte_flow_item_sctp), \ + RTE_MAX(sizeof(struct rte_flow_item_gre), \ + RTE_MAX(sizeof(struct rte_flow_item_ah), \ + RTE_MAX(sizeof(struct rte_flow_item_esp), \ + RTE_MAX(sizeof(struct rte_flow_item_vxlan), \ + RTE_MAX(sizeof(struct rte_flow_item_ecpri), \ + sizeof(struct rte_flow_item_gtp)))))))))))))) * 10) + + #ifndef __cplusplus static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = { - .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - .hdr.ether_type = RTE_BE16(0xffff), + .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", + .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", + .type = RTE_BE16(0xffff), }; static const struct rte_flow_item_vlan dpaa2_flow_item_vlan_mask = { - .hdr.vlan_tci = RTE_BE16(0xffff), + .tci = RTE_BE16(0xffff), }; static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = { .hdr.src_addr = RTE_BE32(0xffffffff), .hdr.dst_addr = RTE_BE32(0xffffffff), .hdr.next_proto_id = 0xff, + .hdr.packet_id = 0xffff, + .hdr.fragment_offset = 0xffff, }; static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = { .hdr = { - .src_addr = RTE_IPV6_MASK_FULL, - .dst_addr = RTE_IPV6_MASK_FULL, + .src_addr = { + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + }, + .dst_addr = { + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + }, .proto = 0xff }, }; @@ -170,7 +256,12 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, + .vni = "\xff\xff\xff", +}; + +static const struct rte_flow_item_geneve dpaa2_flow_item_geneve_mask = { + .protocol = RTE_BE16(0xffff), + .vni = "\xff\xff\xff", }; static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { @@ -184,253 +275,182 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; -static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { - .label_tc_s = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { - .session_id = RTE_BE16(0xffff), -}; - #endif +static inline uint8_t +dpaa2_flow_entry_map_get(const uint8_t *entry_map, + uint16_t index) +{ + uint16_t byte_pos = index / 8; + uint16_t bit_pos = index % 8; -#define DPAA2_FLOW_DUMP printf + return entry_map[byte_pos] & (1 << bit_pos); +} static inline void -dpaa2_prot_field_string(uint32_t prot, uint32_t field, - char *string) +dpaa2_flow_entry_map_set(uint8_t *entry_map, + uint16_t index, int set) { - if (!dpaa2_flow_control_log) - return; + uint16_t byte_pos = index / 8; + uint16_t bit_pos = index % 8; - if (prot == NET_PROT_ETH) { - strcpy(string, "eth"); - if (field == NH_FLD_ETH_DA) - strcat(string, ".dst"); - else if (field == NH_FLD_ETH_SA) - strcat(string, ".src"); - else if (field == NH_FLD_ETH_TYPE) - strcat(string, ".type"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_VLAN) { - strcpy(string, "vlan"); - if (field == NH_FLD_VLAN_TCI) - strcat(string, ".tci"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_IP) { - strcpy(string, "ip"); - if (field == NH_FLD_IP_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_IP_DST) - strcat(string, ".dst"); - else if (field == NH_FLD_IP_PROTO) - strcat(string, ".proto"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_TCP) { - strcpy(string, "tcp"); - if (field == NH_FLD_TCP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_TCP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_UDP) { - strcpy(string, "udp"); - if (field == NH_FLD_UDP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_UDP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_ICMP) { - strcpy(string, "icmp"); - if (field == NH_FLD_ICMP_TYPE) - strcat(string, ".type"); - else if (field == NH_FLD_ICMP_CODE) - strcat(string, ".code"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_SCTP) { - strcpy(string, "sctp"); - if (field == NH_FLD_SCTP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_SCTP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_GRE) { - strcpy(string, "gre"); - if (field == NH_FLD_GRE_TYPE) - strcat(string, ".type"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_GTP) { - rte_strscpy(string, "gtp", DPAA2_PROT_FIELD_STRING_SIZE); - if (field == NH_FLD_GTP_TEID) - strcat(string, ".teid"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_IPSEC_ESP) { - rte_strscpy(string, "esp", DPAA2_PROT_FIELD_STRING_SIZE); - if (field == NH_FLD_IPSEC_ESP_SPI) - strcat(string, ".spi"); - else if (field == NH_FLD_IPSEC_ESP_SEQUENCE_NUM) - strcat(string, ".seq"); - else - strcat(string, ".unknown field"); - } else { - sprintf(string, "unknown protocol(%d)", prot); - } + if (set) + entry_map[byte_pos] |= (1 << bit_pos); + else + entry_map[byte_pos] &= ~(((uint8_t)1) << bit_pos); } static inline void -dpaa2_flow_qos_extracts_log(const struct dpaa2_dev_priv *priv) +dpaa2_flow_extracts_log(const struct dpaa2_dev_priv *priv, + const char *prefix, uint8_t tc_id) { - int idx; - char string[32]; - const struct dpkg_profile_cfg *dpkg = - &priv->extract.qos_key_extract.dpkg; - const struct dpkg_extract *extract; - enum dpkg_extract_type type; - enum net_prot prot; - uint32_t field; + char string[1024]; + const struct dpaa2_flow_tbl_profile *tbl_profile; + int offset = 0; if (!dpaa2_flow_control_log) return; - DPAA2_FLOW_DUMP("QoS table: %d extracts\r\n", - dpkg->num_extracts); - for (idx = 0; idx < dpkg->num_extracts; idx++) { - extract = &dpkg->extracts[idx]; - type = extract->type; - if (type == DPKG_EXTRACT_FROM_HDR) { - prot = extract->extract.from_hdr.prot; - field = extract->extract.from_hdr.field; - dpaa2_prot_field_string(prot, field, - string); - } else if (type == DPKG_EXTRACT_FROM_DATA) { - sprintf(string, "raw offset/len: %d/%d", - extract->extract.from_data.offset, - extract->extract.from_data.size); - } else if (type == DPKG_EXTRACT_FROM_PARSE) { - sprintf(string, "parse offset/len: %d/%d", - extract->extract.from_parse.offset, - extract->extract.from_parse.size); - } - DPAA2_FLOW_DUMP("%s", string); - if ((idx + 1) < dpkg->num_extracts) - DPAA2_FLOW_DUMP(" / "); - } - DPAA2_FLOW_DUMP("\r\n"); + offset += sprintf(&string[offset], + "%s's", priv->eth_dev->data->name); + if (tc_id >= MAX_TCS) { + tbl_profile = &priv->flow_profile.qos_profile; + offset += sprintf(&string[offset], " QoS"); + } else { + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + offset += sprintf(&string[offset], " FS[%d]", tc_id); + } + offset += sprintf(&string[offset], + " table: %d extracts/%d entries\n", + tbl_profile->dpkg.num_extracts, tbl_profile->entry_num); + DPAA2_FLOW_DUMP("\n%s %s", prefix, string); + dpaa2_dump_dpkg(&tbl_profile->dpkg); } static inline void -dpaa2_flow_fs_extracts_log(const struct dpaa2_dev_priv *priv, - int tc_id) +dpaa2_flow_qos_entry_log(const char *log_info, + const struct dpaa2_generic_flow *flow) { int idx; - char string[32]; - const struct dpkg_profile_cfg *dpkg = - &priv->extract.tc_key_extract[tc_id].dpkg; - const struct dpkg_extract *extract; - enum dpkg_extract_type type; - enum net_prot prot; - uint32_t field; + struct rte_eth_dev *dev = flow->priv->eth_dev; if (!dpaa2_flow_control_log) return; - DPAA2_FLOW_DUMP("FS table: %d extracts in TC[%d]\r\n", - dpkg->num_extracts, tc_id); - for (idx = 0; idx < dpkg->num_extracts; idx++) { - extract = &dpkg->extracts[idx]; - type = extract->type; - if (type == DPKG_EXTRACT_FROM_HDR) { - prot = extract->extract.from_hdr.prot; - field = extract->extract.from_hdr.field; - dpaa2_prot_field_string(prot, field, - string); - } else if (type == DPKG_EXTRACT_FROM_DATA) { - sprintf(string, "raw offset/len: %d/%d", - extract->extract.from_data.offset, - extract->extract.from_data.size); - } else if (type == DPKG_EXTRACT_FROM_PARSE) { - sprintf(string, "parse offset/len: %d/%d", - extract->extract.from_parse.offset, - extract->extract.from_parse.size); - } - DPAA2_FLOW_DUMP("%s", string); - if ((idx + 1) < dpkg->num_extracts) - DPAA2_FLOW_DUMP(" / "); - } - DPAA2_FLOW_DUMP("\r\n"); + DPAA2_FLOW_DUMP("%s: %s QoS entry[%d](size %d/%d) to select TC[%d]\n", + dev->data->name, log_info, flow->entry_index, flow->rule_size, + flow->rule_cfg.key_size, + flow->flow_action.qos_action.action_jump_cfg.group); + + DPAA2_FLOW_DUMP("key:\r\n"); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->key_addr[idx]); + + DPAA2_FLOW_DUMP("\r\nmask:\r\n"); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->mask_addr[idx]); + DPAA2_FLOW_DUMP("\r\n\n"); } static inline void -dpaa2_flow_qos_entry_log(const char *log_info, - const struct dpaa2_dev_flow *flow, int qos_index) +dpaa2_flow_fs_entry_log(const char *log_info, + const struct dpaa2_generic_flow *flow) { int idx; - uint8_t *key, *mask; + struct rte_eth_dev *dev = flow->priv->eth_dev; + const struct dpaa2_dev_flow_fs_action *fs_action; if (!dpaa2_flow_control_log) return; - if (qos_index >= 0) { - DPAA2_FLOW_DUMP("%s QoS entry[%d](size %d/%d) for TC[%d]\r\n", - log_info, qos_index, flow->qos_rule_size, - flow->qos_rule.key_size, - flow->tc_id); - } else { - DPAA2_FLOW_DUMP("%s QoS entry(size %d/%d) for TC[%d]\r\n", - log_info, flow->qos_rule_size, - flow->qos_rule.key_size, - flow->tc_id); - } + DPAA2_FLOW_DUMP("%s: %s FS[%d]/entry[%d](size %d/%d)\r\n", + dev->data->name, log_info, flow->tc_id, + flow->entry_index, flow->rule_size, + flow->rule_cfg.key_size); - key = flow->qos_key_addr; - mask = flow->qos_mask_addr; + fs_action = &flow->flow_action.fs_action; DPAA2_FLOW_DUMP("key:\r\n"); - for (idx = 0; idx < flow->qos_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", key[idx]); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->key_addr[idx]); DPAA2_FLOW_DUMP("\r\nmask:\r\n"); - for (idx = 0; idx < flow->qos_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", mask[idx]); - DPAA2_FLOW_DUMP("\r\n"); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->mask_addr[idx]); + DPAA2_FLOW_DUMP("\r\nAction: "); + if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { + DPAA2_FLOW_DUMP("Receive to flow%d\r\n\n", + fs_action->fs_action_cfg.flow_id); + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || + fs_action->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { + DPAA2_FLOW_DUMP("Re-direct to port(s): "); + for (idx = 0; idx < fs_action->fs_action_cfg.num_tokens; idx++) { + DPAA2_FLOW_DUMP("%s", fs_action->dst_name[idx]); + if ((idx + 1) < fs_action->fs_action_cfg.num_tokens) + DPAA2_FLOW_DUMP(", "); + } + DPAA2_FLOW_DUMP("\r\n"); + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + DPAA2_FLOW_DUMP("Drop\r\n\n"); + } else { + DPAA2_FLOW_DUMP("Un-supported action type(%d)\r\n\n", + fs_action->action_type); + } } static inline void -dpaa2_flow_fs_entry_log(const char *log_info, - const struct dpaa2_dev_flow *flow) +dpaa2_dump_extract_map(const struct dpaa2_dev_priv *priv, + const char *prefix, enum dpaa2_flow_dist_type dist_type, + uint8_t group) { - int idx; - uint8_t *key, *mask; + int idx, offset = 0; + char string[2048]; + const struct dpaa2_flow_tbl_profile *tbl_profile; if (!dpaa2_flow_control_log) return; - DPAA2_FLOW_DUMP("%s FS/TC entry[%d](size %d/%d) of TC[%d]\r\n", - log_info, flow->tc_index, - flow->fs_rule_size, flow->fs_rule.key_size, - flow->tc_id); + DPAA2_FLOW_DUMP("%s: %s\n", priv->eth_dev->data->name, prefix); - key = flow->fs_key_addr; - mask = flow->fs_mask_addr; + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + offset += sprintf(&string[offset], "QoS entry map:"); + if (!tbl_profile->entry_num) { + offset += sprintf(&string[offset], " empty\n"); + goto qos_dump_end; + } else { + offset += sprintf(&string[offset], "\n"); + } + for (idx = 0; idx < priv->qos_entries; idx++) { + offset += sprintf(&string[offset], "%d ", + dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx) ? + 1 : 0); + if (!((idx + 1) % 16) || (idx + 1) == priv->qos_entries) + offset += sprintf(&string[offset], "\n"); + } - DPAA2_FLOW_DUMP("key:\r\n"); - for (idx = 0; idx < flow->fs_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", key[idx]); +qos_dump_end: + DPAA2_FLOW_DUMP("%s\n", string); - DPAA2_FLOW_DUMP("\r\nmask:\r\n"); - for (idx = 0; idx < flow->fs_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", mask[idx]); - DPAA2_FLOW_DUMP("\r\n"); + return; + } + + tbl_profile = &priv->flow_profile.tc_profile[group]; + if (!tbl_profile->entry_num) { + DPAA2_FLOW_DUMP("FS[%d] table is empty\n\n", group); + return; + } + + offset = sprintf(&string[offset], + "FS[%d] %d entries:\n", group, tbl_profile->entry_num); + for (idx = 0; idx < priv->fs_entries; idx++) { + offset += sprintf(&string[offset], "%d ", + dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx) ? + 1 : 0); + if (!((idx + 1) % 16) || (idx + 1) == priv->fs_entries) + offset += sprintf(&string[offset], "\n"); + } + DPAA2_FLOW_DUMP("%s\n", string); } static int @@ -487,272 +507,481 @@ dpaa2_flow_l4_dst_port_extract(enum net_prot prot, return false; } +static int +dpaa2_flow_rss_conf_to_item(uint64_t req_dist_set, + struct rte_flow_item *items, uint8_t *spec_buf, + uint32_t buf_max) +{ + uint32_t i = 0, offset = 0; + uint64_t l2_mask, vlan_mask, ipv4_mask, ipv6_mask; + uint64_t dist_supported, udp_mask, tcp_mask, sctp_mask; + struct rte_flow_item_eth *eth = NULL; + struct rte_flow_item_pppoe *pppoe = NULL; + struct rte_flow_item_esp *esp = NULL; + struct rte_flow_item_ah *ah = NULL; + struct rte_flow_item_vlan *vlan = NULL; + struct rte_flow_item_mpls *mpls = NULL; + struct rte_flow_item_gtp *gtpu = NULL; + struct rte_flow_item_udp *udp = NULL; + struct rte_flow_item_tcp *tcp = NULL; + struct rte_flow_item_sctp *sctp = NULL; + struct rte_flow_item_ipv4 *ipv4 = NULL; + + l2_mask = RTE_ETH_RSS_L2_PAYLOAD | RTE_ETH_RSS_ETH; + vlan_mask = RTE_ETH_RSS_C_VLAN | RTE_ETH_RSS_S_VLAN; + ipv4_mask = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | + RTE_ETH_RSS_NONFRAG_IPV4_OTHER; + ipv6_mask = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | + RTE_ETH_RSS_IPV6_EX | RTE_ETH_RSS_NONFRAG_IPV6_OTHER; + udp_mask = RTE_ETH_RSS_NONFRAG_IPV4_UDP | + RTE_ETH_RSS_NONFRAG_IPV6_UDP | + RTE_ETH_RSS_IPV6_UDP_EX; + tcp_mask = RTE_ETH_RSS_NONFRAG_IPV4_TCP | + RTE_ETH_RSS_NONFRAG_IPV6_TCP | + RTE_ETH_RSS_IPV6_TCP_EX; + sctp_mask = RTE_ETH_RSS_NONFRAG_IPV4_SCTP | + RTE_ETH_RSS_NONFRAG_IPV6_SCTP; + dist_supported = l2_mask | vlan_mask | ipv4_mask | + ipv6_mask | udp_mask | tcp_mask | sctp_mask | + RTE_ETH_RSS_GTPU | RTE_ETH_RSS_PPPOE | + RTE_ETH_RSS_ESP | RTE_ETH_RSS_AH | RTE_ETH_RSS_MPLS; + if (~dist_supported & req_dist_set) { + DPAA2_PMD_ERR("%s: Unsupported dist type:0x%" PRIx64, + __func__, (~dist_supported) & req_dist_set); + return -ENOTSUP; + } + + if (req_dist_set & l2_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_ETH; + eth = (void *)(spec_buf + offset); + memset(eth, 0, sizeof(struct rte_flow_item_eth)); + memset(eth->dst.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN); + memset(eth->src.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN); + eth->type = RTE_BE16(0xffff); + items[i].spec = eth; + items[i].mask = eth; + i++; + offset += sizeof(struct rte_flow_item_eth); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_PPPOE) { + items[i].type = RTE_FLOW_ITEM_TYPE_PPPOES; + pppoe = (void *)(spec_buf + offset); + memset(pppoe, 0, sizeof(struct rte_flow_item_pppoe)); + pppoe->session_id = RTE_BE16(0xffff); + items[i].spec = pppoe; + items[i].mask = pppoe; + i++; + offset += sizeof(struct rte_flow_item_pppoe); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_ESP) { + items[i].type = RTE_FLOW_ITEM_TYPE_ESP; + esp = (void *)(spec_buf + offset); + memset(esp, 0, sizeof(struct rte_flow_item_esp)); + esp->hdr.spi = RTE_BE32(0xffffffff); + items[i].spec = esp; + items[i].mask = esp; + i++; + offset += sizeof(struct rte_flow_item_esp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_AH) { + items[i].type = RTE_FLOW_ITEM_TYPE_AH; + ah = (void *)(spec_buf + offset); + memset(ah, 0, sizeof(struct rte_flow_item_ah)); + ah->spi = RTE_BE32(0xffffffff); + items[i].spec = ah; + items[i].mask = ah; + i++; + offset += sizeof(struct rte_flow_item_ah); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & vlan_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_VLAN; + vlan = (void *)(spec_buf + offset); + memset(vlan, 0, sizeof(struct rte_flow_item_vlan)); + vlan->tci = RTE_BE16(0xffff); + items[i].spec = vlan; + items[i].mask = vlan; + i++; + offset += sizeof(struct rte_flow_item_vlan); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_MPLS) { + items[i].type = RTE_FLOW_ITEM_TYPE_MPLS; + mpls = (void *)(spec_buf + offset); + memset(mpls, 0, sizeof(struct rte_flow_item_mpls)); + memset(mpls->label_tc_s, 0xff, 3); + items[i].spec = mpls; + items[i].mask = mpls; + i++; + offset += sizeof(struct rte_flow_item_mpls); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_GTPU) { + items[i].type = RTE_FLOW_ITEM_TYPE_GTPU; + gtpu = (void *)(spec_buf + offset); + memset(gtpu, 0, sizeof(struct rte_flow_item_gtp)); + gtpu->teid = RTE_BE32(0xffffffff); + items[i].spec = gtpu; + items[i].mask = gtpu; + i++; + offset += sizeof(struct rte_flow_item_gtp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & udp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_UDP; + udp = (void *)(spec_buf + offset); + memset(udp, 0, sizeof(struct rte_flow_item_udp)); + udp->hdr.src_port = RTE_BE16(0xffff); + udp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = udp; + items[i].mask = udp; + i++; + offset += sizeof(struct rte_flow_item_udp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & tcp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_TCP; + tcp = (void *)(spec_buf + offset); + memset(tcp, 0, sizeof(struct rte_flow_item_tcp)); + tcp->hdr.src_port = RTE_BE16(0xffff); + tcp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = tcp; + items[i].mask = tcp; + i++; + offset += sizeof(struct rte_flow_item_tcp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & sctp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_SCTP; + sctp = (void *)(spec_buf + offset); + memset(sctp, 0, sizeof(struct rte_flow_item_sctp)); + sctp->hdr.src_port = RTE_BE16(0xffff); + sctp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = sctp; + items[i].mask = sctp; + i++; + offset += sizeof(struct rte_flow_item_sctp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & ipv4_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_IPV4; + ipv4 = (void *)(spec_buf + offset); + memset(ipv4, 0, sizeof(struct rte_flow_item_ipv4)); + ipv4->hdr.src_addr = RTE_BE32(0xffffffff); + ipv4->hdr.dst_addr = RTE_BE32(0xffffffff); + ipv4->hdr.next_proto_id = 0xff; + items[i].spec = ipv4; + items[i].mask = ipv4; + i++; + offset += sizeof(struct rte_flow_item_ipv4); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + items[i].type = RTE_FLOW_ITEM_TYPE_END; + + return i; +} + static int dpaa2_flow_add_qos_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow) + struct dpaa2_generic_flow *flow) { - uint16_t qos_index; + struct dpaa2_flow_tbl_profile *tbl_profile; int ret; struct fsl_mc_io *dpni = priv->hw; + uint8_t flags = DPNI_QOS_OPT_SET_TC_ONLY, flow_id = 0; - if (priv->num_rx_tc <= 1 && - flow->action_type != RTE_FLOW_ACTION_TYPE_RSS) { - DPAA2_PMD_WARN("No QoS Table for FS"); + if (flow->entry_index >= priv->qos_entries) { + DPAA2_PMD_ERR("QoS table full(%d >= %d)", + flow->entry_index, priv->qos_entries); + return -EINVAL; + } + tbl_profile = &priv->flow_profile.qos_profile; + if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, + flow->entry_index)) { + DPAA2_PMD_ERR("QoS entry[%d] has been occupied", + flow->entry_index); return -EINVAL; } - /* QoS entry added is only effective for multiple TCs.*/ - qos_index = flow->tc_id * priv->fs_entries + flow->tc_index; - if (qos_index >= priv->qos_entries) { - DPAA2_PMD_ERR("QoS table full(%d >= %d)", - qos_index, priv->qos_entries); + if (flow->flow_action.qos_action.action_jump_type != + RTE_FLOW_ACTION_TYPE_JUMP) { + DPAA2_PMD_ERR("QoS entry[%d]'jump action not set(%d)", + flow->entry_index, + flow->flow_action.qos_action.action_jump_type); + return -EINVAL; + } + if (flow->flow_action.qos_action.action_jump_cfg.group >= + priv->num_rx_tc) { + DPAA2_PMD_ERR("QoS entry[%d]'dest table ID(%d) >= max(%d)", + flow->entry_index, + flow->flow_action.qos_action.action_jump_cfg.group, + priv->num_rx_tc); return -EINVAL; } - dpaa2_flow_qos_entry_log("Start add", flow, qos_index); + dpaa2_flow_qos_entry_log("Add", flow); + if (flow->direct_queue) { + flags |= DPNI_QOS_OPT_SET_FLOW_ID; + flow_id = flow->flow_id; + } ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, - priv->token, &flow->qos_rule, - flow->tc_id, qos_index, - 0, 0); + priv->token, &flow->rule_cfg, + flow->flow_action.qos_action.action_jump_cfg.group, + flow->entry_index, flags, flow_id); if (ret < 0) { DPAA2_PMD_ERR("Add entry(%d) to table(%d) failed", - qos_index, flow->tc_id); + flow->entry_index, + flow->flow_action.qos_action.action_jump_cfg.group); return ret; } + dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 1); + tbl_profile->entry_num++; return 0; } static int dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow) + struct dpaa2_generic_flow *flow) { + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_flow_tbl_profile *tbl_profile; int ret; struct fsl_mc_io *dpni = priv->hw; - if (flow->tc_index >= priv->fs_entries) { - DPAA2_PMD_ERR("FS table full(%d >= %d)", - flow->tc_index, priv->fs_entries); + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + tbl_profile = &priv->flow_profile.tc_profile[flow->tc_id]; + if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, + flow->entry_index)) { + DPAA2_PMD_ERR("FS[%d].entry[%d] has been occupied", + flow->tc_id, flow->entry_index); return -EINVAL; } - dpaa2_flow_fs_entry_log("Start add", flow); + dpaa2_flow_fs_entry_log("Add", flow); - ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, - priv->token, flow->tc_id, - flow->tc_index, &flow->fs_rule, - &flow->fs_action_cfg); + if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { + ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg); + } else { + ret = dpni_add_fs_entry_legacy(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg); + } if (ret < 0) { DPAA2_PMD_ERR("Add rule(%d) to FS table(%d) failed", - flow->tc_index, flow->tc_id); + flow->entry_index, flow->tc_id); return ret; } + dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 1); + tbl_profile->entry_num++; + return 0; } static int -dpaa2_flow_rule_insert_hole(struct dpaa2_dev_flow *flow, - int offset, int size, - enum dpaa2_flow_dist_type dist_type) +dpaa2_flow_update_qos_rule_action(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow) { - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - if (offset < flow->qos_rule_size) { - memmove(flow->qos_key_addr + offset + size, - flow->qos_key_addr + offset, - flow->qos_rule_size - offset); - memset(flow->qos_key_addr + offset, - 0, size); - - memmove(flow->qos_mask_addr + offset + size, - flow->qos_mask_addr + offset, - flow->qos_rule_size - offset); - memset(flow->qos_mask_addr + offset, - 0, size); - flow->qos_rule_size += size; - } else { - flow->qos_rule_size = offset + size; - } + int ret; + struct fsl_mc_io *dpni = priv->hw; + uint8_t flags = DPNI_QOS_OPT_UPDATE_IF_EXISTS, flow_id = 0; + + dpaa2_flow_qos_entry_log("Update action", flow); + + if (flow->direct_queue) { + flags |= DPNI_QOS_OPT_SET_FLOW_ID; + flow_id = flow->flow_id; } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - if (offset < flow->fs_rule_size) { - memmove(flow->fs_key_addr + offset + size, - flow->fs_key_addr + offset, - flow->fs_rule_size - offset); - memset(flow->fs_key_addr + offset, - 0, size); - - memmove(flow->fs_mask_addr + offset + size, - flow->fs_mask_addr + offset, - flow->fs_rule_size - offset); - memset(flow->fs_mask_addr + offset, - 0, size); - flow->fs_rule_size += size; - } else { - flow->fs_rule_size = offset + size; - } + /** This option doesn't support legacy operation.*/ + ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, + priv->token, &flow->rule_cfg, + flow->flow_action.qos_action.action_jump_cfg.group, + flow->entry_index, + flags, flow_id); + if (ret < 0) { + DPAA2_PMD_ERR("Update rule(%d) in QOS table failed(%d)", + flow->entry_index, ret); + return ret; } return 0; } static int -dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv, - enum dpaa2_flow_dist_type dist_type, - uint16_t entry_size, uint8_t tc_id) +dpaa2_flow_update_fs_rule_action(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow) { - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); int ret; + struct fsl_mc_io *dpni = priv->hw; + struct dpni_fs_action_cfg *cfg; - while (curr) { - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - if (priv->num_rx_tc > 1 || - curr->action_type == - RTE_FLOW_ACTION_TYPE_RSS) { - curr->qos_rule.key_size = entry_size; - ret = dpaa2_flow_add_qos_rule(priv, curr); - if (ret) - return ret; - } - } - if (dist_type & DPAA2_FLOW_FS_TYPE && - curr->tc_id == tc_id) { - curr->fs_rule.key_size = entry_size; - ret = dpaa2_flow_add_fs_rule(priv, curr); - if (ret) - return ret; - } - curr = LIST_NEXT(curr, next); + dpaa2_flow_fs_entry_log("Update action", flow); + + cfg = &flow->flow_action.fs_action.fs_action_cfg; + cfg->options |= DPNI_FS_OPT_UPDATE_IF_EXISTS; + /** This option doesn't support legacy operation.*/ + ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, cfg); + if (ret < 0) { + DPAA2_PMD_ERR("Update rule(%d) in FS table(%d) failed", + flow->entry_index, flow->tc_id); + return ret; } return 0; } static int -dpaa2_flow_qos_rule_insert_hole(struct dpaa2_dev_priv *priv, +_dpaa2_flow_rule_insert_hole(struct dpaa2_generic_flow *flow, int offset, int size) { - struct dpaa2_dev_flow *curr; - int ret; - - curr = priv->curr; - if (!curr) { - DPAA2_PMD_ERR("Current qos flow insert hole failed."); - return -EINVAL; + if (offset < flow->rule_size) { + memmove(flow->key_addr + offset + size, + flow->key_addr + offset, + flow->rule_size - offset); + memset(flow->key_addr + offset, 0, size); + + memmove(flow->mask_addr + offset + size, + flow->mask_addr + offset, + flow->rule_size - offset); + memset(flow->mask_addr + offset, 0, size); + flow->rule_size += size; } else { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - } - - curr = LIST_FIRST(&priv->flows); - while (curr) { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - curr = LIST_NEXT(curr, next); + flow->rule_size = offset + size; } return 0; } static int -dpaa2_flow_fs_rule_insert_hole(struct dpaa2_dev_priv *priv, - int offset, int size, int tc_id) +dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type dist_type, + uint16_t entry_size, uint8_t tc_id) { - struct dpaa2_dev_flow *curr; + struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); + struct dpaa2_generic_flow *qos_flow; + struct dpaa2_generic_flow *fs_flow; int ret; - curr = priv->curr; - if (!curr || curr->tc_id != tc_id) { - DPAA2_PMD_ERR("Current flow insert hole failed."); - return -EINVAL; - } else { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - curr = LIST_FIRST(&priv->flows); - while (curr) { - if (curr->tc_id != tc_id) { - curr = LIST_NEXT(curr, next); - continue; + qos_flow = curr->qos_flow; + fs_flow = curr->fs_flow; + if (qos_flow && dist_type == DPAA2_FLOW_QOS_TYPE) { + qos_flow->rule_cfg.key_size = entry_size; + ret = dpaa2_flow_add_qos_rule(priv, qos_flow); + if (ret) + return ret; + } else if (dist_type == DPAA2_FLOW_FS_TYPE && + fs_flow && fs_flow->tc_id == tc_id) { + fs_flow->rule_cfg.key_size = entry_size; + ret = dpaa2_flow_add_fs_rule(priv, fs_flow); + if (ret) + return ret; } - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; curr = LIST_NEXT(curr, next); } return 0; } +static void +dpaa2_flow_rule_insert_hole(struct dpaa2_dev_priv *priv, + int offset, int size, int tc_id, + enum dpaa2_flow_dist_type dist_type) +{ + struct dpaa2_dev_flow *flow; + struct dpaa2_generic_flow *curr; + + curr = priv->cur_flow; + if (curr) + _dpaa2_flow_rule_insert_hole(curr, offset, size); + + flow = LIST_FIRST(&priv->flows); + while (flow) { + if (dist_type == DPAA2_FLOW_QOS_TYPE) + curr = flow->qos_flow; + else + curr = flow->fs_flow; + flow = LIST_NEXT(flow, next); + if (!curr) + continue; + if (dist_type == DPAA2_FLOW_FS_TYPE && + curr->tc_id != tc_id) + continue; + if (curr->ip_src || curr->ip_dst) + _dpaa2_flow_rule_insert_hole(curr, offset, size); + } +} + static int dpaa2_flow_faf_advance(struct dpaa2_dev_priv *priv, int faf_byte, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int offset, ret; struct dpaa2_key_profile *key_profile; - int num, pos; + uint8_t idx, offset = 0xff; + struct key_prot_field prot = {0}; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; + key_profile = &priv->flow_profile.qos_profile.key_profile; else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - - num = key_profile->num; + key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile; - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off++; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, 1); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, 1, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - - key_profile->key_size[pos] = 1; - key_profile->prot_field[pos].type = DPAA2_FAF_KEY; - key_profile->prot_field[pos].key_field = faf_byte; - key_profile->num++; + prot.type = DPAA2_FAF_KEY; + prot.key_field = faf_byte; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + 1, &offset, insert_offset, &prot); + dpaa2_flow_rule_insert_hole(priv, offset, 1, tc_id, dist_type); - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; - - key_profile->key_max_size++; - - return pos; + return idx; } static int @@ -761,60 +990,27 @@ dpaa2_flow_pr_advance(struct dpaa2_dev_priv *priv, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int offset, ret; struct dpaa2_key_profile *key_profile; - int num, pos; + uint8_t idx, offset = 0xff; + struct key_prot_field prot = {0}; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; + key_profile = &priv->flow_profile.qos_profile.key_profile; else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - - num = key_profile->num; + key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile; - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off += pr_size; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, pr_size); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, pr_size, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - - key_profile->key_size[pos] = pr_size; - key_profile->prot_field[pos].type = DPAA2_PR_KEY; - key_profile->prot_field[pos].key_field = - (pr_offset << 16) | pr_size; - key_profile->num++; - - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; + prot.type = DPAA2_PR_KEY; + prot.key_field = (pr_offset << 16) | pr_size; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + pr_size, &offset, insert_offset, &prot); + dpaa2_flow_rule_insert_hole(priv, offset, pr_size, tc_id, dist_type); - key_profile->key_max_size += pr_size; - - return pos; + return idx; } /* Move IPv4/IPv6 addresses to fill new extract previous IP address. @@ -829,9 +1025,9 @@ dpaa2_flow_key_profile_advance(enum net_prot prot, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int offset, ret; struct dpaa2_key_profile *key_profile; - int num, pos; + uint8_t idx, offset = 0xff; + struct key_prot_field prot_field; if (dpaa2_flow_ip_address_extract(prot, field)) { DPAA2_PMD_ERR("%s only for none IP address extract", @@ -840,66 +1036,35 @@ dpaa2_flow_key_profile_advance(enum net_prot prot, } if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; + key_profile = &priv->flow_profile.qos_profile.key_profile; else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - - num = key_profile->num; + key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile; - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off += field_size; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, field_size); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, field_size, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - - key_profile->key_size[pos] = field_size; - key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY; - key_profile->prot_field[pos].prot = prot; - key_profile->prot_field[pos].key_field = field; - key_profile->num++; - - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; + prot_field.type = DPAA2_NET_PROT_KEY; + prot_field.prot = prot; + prot_field.key_field = field; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + field_size, &offset, insert_offset, &prot_field); + dpaa2_flow_rule_insert_hole(priv, offset, field_size, tc_id, dist_type); if (dpaa2_flow_l4_src_port_extract(prot, field)) { - key_profile->l4_src_port_present = 1; - key_profile->l4_src_port_pos = pos; - key_profile->l4_src_port_offset = - key_profile->key_offset[pos]; + key_profile->l4_sp_present = 1; + key_profile->l4_sp_extract_idx = idx; + key_profile->l4_sp_key_offset = + key_profile->key_offset[idx]; } else if (dpaa2_flow_l4_dst_port_extract(prot, field)) { - key_profile->l4_dst_port_present = 1; - key_profile->l4_dst_port_pos = pos; - key_profile->l4_dst_port_offset = - key_profile->key_offset[pos]; + key_profile->l4_dp_present = 1; + key_profile->l4_dp_extract_idx = idx; + key_profile->l4_dp_key_offset = + key_profile->key_offset[idx]; } - key_profile->key_max_size += field_size; - return pos; + return idx; } static int @@ -908,44 +1073,34 @@ dpaa2_flow_faf_add_hdr(int faf_byte, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int pos, i, offset; - struct dpaa2_key_extract *key_extract; + int extract_idx; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; + struct dpkg_extract extract; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + dpkg = &tbl_profile->dpkg; if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - pos = dpaa2_flow_faf_advance(priv, + extract_idx = dpaa2_flow_faf_advance(priv, faf_byte, dist_type, tc_id, insert_offset); - if (pos < 0) - return pos; - - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } - } - - offset = DPAA2_FAFE_PSR_OFFSET + faf_byte; - - extracts[pos].type = DPKG_EXTRACT_FROM_PARSE; - extracts[pos].extract.from_parse.offset = offset; - extracts[pos].extract.from_parse.size = 1; + if (extract_idx < 0) + return extract_idx; - dpkg->num_extracts++; + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_PARSE; + extract.extract.from_parse.offset = faf_byte; + extract.extract.from_parse.size = 1; + dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract); return 0; } @@ -956,48 +1111,40 @@ dpaa2_flow_pr_add_hdr(uint32_t pr_offset, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int pos, i; - struct dpaa2_key_extract *key_extract; + int extract_idx; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; + struct dpkg_extract extract; - if ((pr_offset + pr_size) > DPAA2_FAPR_SIZE) { + if ((pr_offset + pr_size) > DPAA2_PSR_RESULT_SIZE) { DPAA2_PMD_ERR("PR extracts(%d:%d) overflow", pr_offset, pr_size); return -EINVAL; } if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + dpkg = &tbl_profile->dpkg; if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - pos = dpaa2_flow_pr_advance(priv, + extract_idx = dpaa2_flow_pr_advance(priv, pr_offset, pr_size, dist_type, tc_id, insert_offset); - if (pos < 0) - return pos; + if (extract_idx < 0) + return extract_idx; - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } - } - - extracts[pos].type = DPKG_EXTRACT_FROM_PARSE; - extracts[pos].extract.from_parse.offset = pr_offset; - extracts[pos].extract.from_parse.size = pr_size; - - dpkg->num_extracts++; + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_PARSE; + extract.extract.from_parse.offset = pr_offset; + extract.extract.from_parse.size = pr_size; + dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract); return 0; } @@ -1009,18 +1156,17 @@ dpaa2_flow_extract_add_hdr(enum net_prot prot, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int pos, i; - struct dpaa2_key_extract *key_extract; + int extract_idx; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; + struct dpkg_extract extract; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + dpkg = &tbl_profile->dpkg; if (dpaa2_flow_ip_address_extract(prot, field)) { DPAA2_PMD_ERR("%s only for none IP address extract", @@ -1033,52 +1179,86 @@ dpaa2_flow_extract_add_hdr(enum net_prot prot, return -EINVAL; } - pos = dpaa2_flow_key_profile_advance(prot, + extract_idx = dpaa2_flow_key_profile_advance(prot, field, field_size, priv, dist_type, tc_id, insert_offset); - if (pos < 0) - return pos; + if (extract_idx < 0) + return extract_idx; - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_HDR; + extract.extract.from_hdr.prot = prot; + extract.extract.from_hdr.type = DPKG_FULL_FIELD; + extract.extract.from_hdr.field = field; + dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract); + + return 0; +} + +static inline int +dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile, + enum key_prot_type type, enum net_prot prot, uint32_t key_field) +{ + int extract_idx; + struct key_prot_field *prot_field; + + if (dpaa2_flow_ip_address_extract(prot, key_field)) { + DPAA2_PMD_ERR("%s only for none IP address extract", + __func__); + return -EINVAL; } - extracts[pos].type = DPKG_EXTRACT_FROM_HDR; - extracts[pos].extract.from_hdr.prot = prot; - extracts[pos].extract.from_hdr.type = DPKG_FULL_FIELD; - extracts[pos].extract.from_hdr.field = field; + prot_field = key_profile->prot_field; + for (extract_idx = 0; extract_idx < key_profile->num; extract_idx++) { + if (type == DPAA2_NET_PROT_KEY && + prot_field[extract_idx].prot == prot && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + else if (type == DPAA2_FAF_KEY && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + else if (type == DPAA2_PR_KEY && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + } - dpkg->num_extracts++; + if (type == DPAA2_NET_PROT_KEY && + dpaa2_flow_l4_src_port_extract(prot, key_field)) { + if (key_profile->l4_sp_present) + return key_profile->l4_sp_extract_idx; + } else if (type == DPAA2_NET_PROT_KEY && + dpaa2_flow_l4_dst_port_extract(prot, key_field)) { + if (key_profile->l4_dp_present) + return key_profile->l4_dp_extract_idx; + } - return 0; + return -ENXIO; } static int -dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, +_dpaa2_flow_extract_add_raw(struct dpaa2_dev_priv *priv, int offset, int size, enum dpaa2_flow_dist_type dist_type, int tc_id) { - struct dpaa2_key_extract *key_extract; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; struct dpaa2_key_profile *key_profile; - int last_extract_size, index, pos, item_size; + int last_extract_size, index, raw_idx, item_size; uint8_t num_extracts; uint32_t field; + int ret; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - dpkg = &key_extract->dpkg; - key_profile = &key_extract->key_profile; - - key_profile->raw_region.raw_start = 0; - key_profile->raw_region.raw_size = 0; + dpkg = &tbl_profile->dpkg; + key_profile = &tbl_profile->key_profile; last_extract_size = (size % DPAA2_FLOW_MAX_KEY_SIZE); num_extracts = (size / DPAA2_FLOW_MAX_KEY_SIZE); @@ -1087,6 +1267,13 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, else last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE; + if ((key_profile->num + num_extracts) > + DPKG_MAX_NUM_OF_EXTRACTS) { + DPAA2_PMD_ERR("%s Failed to expand raw extracts", + __func__); + return -EINVAL; + } + for (index = 0; index < num_extracts; index++) { if (index == num_extracts - 1) item_size = last_extract_size; @@ -1095,25 +1282,22 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; field |= item_size; - pos = dpaa2_flow_key_profile_advance(NET_PROT_PAYLOAD, + ret = dpaa2_flow_extract_search(key_profile, + DPAA2_NET_PROT_KEY, NET_PROT_PAYLOAD, field); + if (ret >= 0) { + offset += item_size; + continue; + } + + raw_idx = dpaa2_flow_key_profile_advance(NET_PROT_PAYLOAD, field, item_size, priv, dist_type, tc_id, NULL); - if (pos < 0) - return pos; - - dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA; - dpkg->extracts[pos].extract.from_data.size = item_size; - dpkg->extracts[pos].extract.from_data.offset = offset; - - if (index == 0) { - key_profile->raw_extract_pos = pos; - key_profile->raw_extract_off = - key_profile->key_offset[pos]; - key_profile->raw_region.raw_start = offset; - } - key_profile->raw_extract_num++; - key_profile->raw_region.raw_size += - key_profile->key_size[pos]; + if (raw_idx < 0) + return raw_idx; + + dpkg->extracts[raw_idx].type = DPKG_EXTRACT_FROM_DATA; + dpkg->extracts[raw_idx].extract.from_data.size = item_size; + dpkg->extracts[raw_idx].extract.from_data.offset = offset; offset += item_size; dpkg->num_extracts++; @@ -1127,247 +1311,16 @@ dpaa2_flow_extract_add_raw(struct dpaa2_dev_priv *priv, int offset, int size, enum dpaa2_flow_dist_type dist_type, int tc_id, int *recfg) { - struct dpaa2_key_profile *key_profile; - struct dpaa2_raw_region *raw_region; - int end = offset + size, ret = 0, extract_extended, sz_extend; - int start_cmp, end_cmp, new_size, index, pos, end_pos; - int last_extract_size, item_size, num_extracts, bk_num = 0; - struct dpkg_extract extract_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - uint8_t key_offset_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - uint8_t key_size_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - struct key_prot_field prot_field_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - struct dpaa2_raw_region raw_hole; - struct dpkg_profile_cfg *dpkg; - enum net_prot prot; - uint32_t field; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - key_profile = &priv->extract.qos_key_extract.key_profile; - dpkg = &priv->extract.qos_key_extract.dpkg; - } else { - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - dpkg = &priv->extract.tc_key_extract[tc_id].dpkg; - } + int ret; - raw_region = &key_profile->raw_region; - if (!raw_region->raw_size) { - /* New RAW region*/ - ret = dpaa2_flow_extract_new_raw(priv, offset, size, + ret = _dpaa2_flow_extract_add_raw(priv, offset, size, dist_type, tc_id); - if (!ret && recfg) - (*recfg) |= dist_type; - - return ret; - } - start_cmp = raw_region->raw_start; - end_cmp = raw_region->raw_start + raw_region->raw_size; - - if (offset >= start_cmp && end <= end_cmp) - return 0; - - sz_extend = 0; - new_size = raw_region->raw_size; - if (offset < start_cmp) { - sz_extend += start_cmp - offset; - new_size += (start_cmp - offset); - } - if (end > end_cmp) { - sz_extend += end - end_cmp; - new_size += (end - end_cmp); - } - - last_extract_size = (new_size % DPAA2_FLOW_MAX_KEY_SIZE); - num_extracts = (new_size / DPAA2_FLOW_MAX_KEY_SIZE); - if (last_extract_size) - num_extracts++; - else - last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE; - - if ((key_profile->num + num_extracts - - key_profile->raw_extract_num) >= - DPKG_MAX_NUM_OF_EXTRACTS) { - DPAA2_PMD_ERR("%s Failed to expand raw extracts", - __func__); - return -EINVAL; - } - - if (offset < start_cmp) { - raw_hole.raw_start = key_profile->raw_extract_off; - raw_hole.raw_size = start_cmp - offset; - raw_region->raw_start = offset; - raw_region->raw_size += start_cmp - offset; - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size); - if (ret) - return ret; - } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size, tc_id); - if (ret) - return ret; - } - } - - if (end > end_cmp) { - raw_hole.raw_start = - key_profile->raw_extract_off + - raw_region->raw_size; - raw_hole.raw_size = end - end_cmp; - raw_region->raw_size += end - end_cmp; - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size); - if (ret) - return ret; - } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size, tc_id); - if (ret) - return ret; - } - } - - end_pos = key_profile->raw_extract_pos + - key_profile->raw_extract_num; - if (key_profile->num > end_pos) { - bk_num = key_profile->num - end_pos; - memcpy(extract_bk, &dpkg->extracts[end_pos], - bk_num * sizeof(struct dpkg_extract)); - memcpy(key_offset_bk, &key_profile->key_offset[end_pos], - bk_num * sizeof(uint8_t)); - memcpy(key_size_bk, &key_profile->key_size[end_pos], - bk_num * sizeof(uint8_t)); - memcpy(prot_field_bk, &key_profile->prot_field[end_pos], - bk_num * sizeof(struct key_prot_field)); - - for (index = 0; index < bk_num; index++) { - key_offset_bk[index] += sz_extend; - prot = prot_field_bk[index].prot; - field = prot_field_bk[index].key_field; - if (dpaa2_flow_l4_src_port_extract(prot, - field)) { - key_profile->l4_src_port_present = 1; - key_profile->l4_src_port_pos = end_pos + index; - key_profile->l4_src_port_offset = - key_offset_bk[index]; - } else if (dpaa2_flow_l4_dst_port_extract(prot, - field)) { - key_profile->l4_dst_port_present = 1; - key_profile->l4_dst_port_pos = end_pos + index; - key_profile->l4_dst_port_offset = - key_offset_bk[index]; - } - } - } - - pos = key_profile->raw_extract_pos; - - for (index = 0; index < num_extracts; index++) { - if (index == num_extracts - 1) - item_size = last_extract_size; - else - item_size = DPAA2_FLOW_MAX_KEY_SIZE; - field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; - field |= item_size; - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - key_profile->key_size[pos] = item_size; - key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY; - key_profile->prot_field[pos].prot = NET_PROT_PAYLOAD; - key_profile->prot_field[pos].key_field = field; - - dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA; - dpkg->extracts[pos].extract.from_data.size = item_size; - dpkg->extracts[pos].extract.from_data.offset = offset; - offset += item_size; - pos++; - } - - if (bk_num) { - memcpy(&dpkg->extracts[pos], extract_bk, - bk_num * sizeof(struct dpkg_extract)); - memcpy(&key_profile->key_offset[end_pos], - key_offset_bk, bk_num * sizeof(uint8_t)); - memcpy(&key_profile->key_size[end_pos], - key_size_bk, bk_num * sizeof(uint8_t)); - memcpy(&key_profile->prot_field[end_pos], - prot_field_bk, bk_num * sizeof(struct key_prot_field)); - } - - extract_extended = num_extracts - key_profile->raw_extract_num; - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - key_profile->ip_addr_extract_pos += extract_extended; - key_profile->ip_addr_extract_off += sz_extend; - } - key_profile->raw_extract_num = num_extracts; - key_profile->num += extract_extended; - key_profile->key_max_size += sz_extend; - - dpkg->num_extracts += extract_extended; if (!ret && recfg) - (*recfg) |= dist_type; + (*recfg) |= true; return ret; } -static inline int -dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile, - enum key_prot_type type, enum net_prot prot, uint32_t key_field) -{ - int pos; - struct key_prot_field *prot_field; - - if (dpaa2_flow_ip_address_extract(prot, key_field)) { - DPAA2_PMD_ERR("%s only for none IP address extract", - __func__); - return -EINVAL; - } - - prot_field = key_profile->prot_field; - for (pos = 0; pos < key_profile->num; pos++) { - if (type == DPAA2_NET_PROT_KEY && - prot_field[pos].prot == prot && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - else if (type == DPAA2_FAF_KEY && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - else if (type == DPAA2_PR_KEY && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - } - - if (type == DPAA2_NET_PROT_KEY && - dpaa2_flow_l4_src_port_extract(prot, key_field)) { - if (key_profile->l4_src_port_present) - return key_profile->l4_src_port_pos; - } else if (type == DPAA2_NET_PROT_KEY && - dpaa2_flow_l4_dst_port_extract(prot, key_field)) { - if (key_profile->l4_dst_port_present) - return key_profile->l4_dst_port_pos; - } - - return -ENXIO; -} - static inline int dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile, enum key_prot_type type, enum net_prot prot, uint32_t key_field) @@ -1383,71 +1336,45 @@ dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile, static int dpaa2_flow_faf_add_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, - enum dpaa2_rx_faf_offset faf_bit_off, - int group, - enum dpaa2_flow_dist_type dist_type) + struct dpaa2_generic_flow *flow, uint32_t faf_bit_off, + int group, enum dpaa2_flow_dist_type dist_type) { int offset; uint8_t *key_addr; uint8_t *mask_addr; - struct dpaa2_key_extract *key_extract; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; uint8_t faf_byte = faf_bit_off / 8; uint8_t faf_bit_in_byte = faf_bit_off % 8; faf_bit_in_byte = 7 - faf_bit_in_byte; - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - key_extract = &priv->extract.qos_key_extract; - key_profile = &key_extract->key_profile; - - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (offset < 0) { - DPAA2_PMD_ERR("%s QoS key extract failed", __func__); - return -EINVAL; - } - key_addr = flow->qos_key_addr + offset; - mask_addr = flow->qos_mask_addr + offset; - - if (!(*key_addr) && - key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT && - offset >= flow->qos_rule_size) - flow->qos_rule_size = offset + sizeof(uint8_t); - - *key_addr |= (1 << faf_bit_in_byte); - *mask_addr |= (1 << faf_bit_in_byte); + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[group]; + key_profile = &tbl_profile->key_profile; + offset = dpaa2_flow_extract_key_offset(key_profile, + DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); + if (offset < 0) { + DPAA2_PMD_ERR("%s QoS key extract failed", __func__); + return -EINVAL; } + key_addr = flow->key_addr + offset; + mask_addr = flow->mask_addr + offset; - if (dist_type & DPAA2_FLOW_FS_TYPE) { - key_extract = &priv->extract.tc_key_extract[group]; - key_profile = &key_extract->key_profile; - - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (offset < 0) { - DPAA2_PMD_ERR("%s TC[%d] key extract failed", - __func__, group); - return -EINVAL; - } - key_addr = flow->fs_key_addr + offset; - mask_addr = flow->fs_mask_addr + offset; - - if (!(*key_addr) && - key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT && - offset >= flow->fs_rule_size) - flow->fs_rule_size = offset + sizeof(uint8_t); + if (!(*key_addr) && + !(flow->ip_src || flow->ip_dst) && + offset >= flow->rule_size) + flow->rule_size = offset + sizeof(uint8_t); - *key_addr |= (1 << faf_bit_in_byte); - *mask_addr |= (1 << faf_bit_in_byte); - } + *key_addr |= (1 << faf_bit_in_byte); + *mask_addr |= (1 << faf_bit_in_byte); return 0; } static inline int -dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow, +dpaa2_flow_pr_rule_data_set(struct dpaa2_generic_flow *flow, struct dpaa2_key_profile *key_profile, uint32_t pr_offset, uint32_t pr_size, const void *key, const void *mask, @@ -1467,39 +1394,20 @@ dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow, sprintf(offset_info, "offset(%d)", offset); sprintf(size_info, "size(%d)", pr_size); - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, pr_size); - memcpy((flow->qos_mask_addr + offset), mask, pr_size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + pr_size; - } else if ((offset + pr_size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", - offset_info, rule_size_info, - offset_info, size_info, - rule_size_info); - return -EINVAL; - } - } - } - - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, pr_size); - memcpy((flow->fs_mask_addr + offset), mask, pr_size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + pr_size; - } else if ((offset + pr_size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", - offset_info, rule_size_info, - offset_info, size_info, - rule_size_info); - return -EINVAL; - } + sprintf(rule_size_info, "%s rule size(%d)", + dist_type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", flow->rule_size); + memcpy((flow->key_addr + offset), key, pr_size); + memcpy((flow->mask_addr + offset), mask, pr_size); + if (!(flow->ip_src || flow->ip_dst)) { + if (offset >= flow->rule_size) { + flow->rule_size = offset + pr_size; + } else if ((offset + pr_size) > flow->rule_size) { + DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", + offset_info, rule_size_info, + offset_info, size_info, + rule_size_info); + return -EINVAL; } } @@ -1507,13 +1415,13 @@ dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow, } static inline int -dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow, +dpaa2_flow_hdr_rule_data_set(struct dpaa2_generic_flow *flow, struct dpaa2_key_profile *key_profile, enum net_prot prot, uint32_t field, int size, const void *key, const void *mask, enum dpaa2_flow_dist_type dist_type) { - int offset; + int offset, i; char offset_info[64], size_info[64], rule_size_info[64]; if (dpaa2_flow_ip_address_extract(prot, field)) { @@ -1532,37 +1440,22 @@ dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow, sprintf(offset_info, "offset(%d)", offset); sprintf(size_info, "size(%d)", size); - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, size); - memcpy((flow->qos_mask_addr + offset), mask, size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + size; - } else if ((offset + size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } - } - } + sprintf(rule_size_info, "%s rule size(%d)", + dist_type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", + flow->rule_size); - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, size); - memcpy((flow->fs_mask_addr + offset), mask, size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + size; - } else if ((offset + size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } + for (i = 0; i < size; i++) { + *(flow->key_addr + offset + i) |= *((const uint8_t *)key + i); + *(flow->mask_addr + offset + i) |= *((const uint8_t *)mask + i); + } + if (!(flow->ip_src || flow->ip_dst)) { + if (offset >= flow->rule_size) { + flow->rule_size = offset + size; + } else if ((offset + size) > flow->rule_size) { + DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", + __func__, offset_info, rule_size_info, + offset_info, size_info, rule_size_info); + return -EINVAL; } } @@ -1570,7 +1463,7 @@ dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow, } static inline int -dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow, +dpaa2_flow_raw_rule_data_set(struct dpaa2_generic_flow *flow, struct dpaa2_key_profile *key_profile, uint32_t extract_offset, int size, const void *key, const void *mask, @@ -1593,34 +1486,19 @@ dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow, sprintf(offset_info, "offset(%d)", offset); sprintf(size_info, "size(%d)", size); - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, size); - memcpy((flow->qos_mask_addr + offset), mask, size); - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + size; - } else if ((offset + size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } - } - - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, size); - memcpy((flow->fs_mask_addr + offset), mask, size); - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + size; - } else if ((offset + size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } + sprintf(rule_size_info, "%s rule size(%d)", + dist_type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", flow->rule_size); + + memcpy((flow->key_addr + offset), key, size); + memcpy((flow->mask_addr + offset), mask, size); + if (offset >= flow->rule_size) { + flow->rule_size = offset + size; + } else if ((offset + size) > flow->rule_size) { + DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", + __func__, offset_info, rule_size_info, + offset_info, size_info, rule_size_info); + return -EINVAL; } return 0; @@ -1691,13 +1569,9 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; - case RTE_FLOW_ITEM_TYPE_MPLS: - mask_support = (const char *)&dpaa2_flow_item_mpls_mask; - size = sizeof(struct rte_flow_item_mpls); - break; - case RTE_FLOW_ITEM_TYPE_PPPOES: - mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; - size = sizeof(struct rte_flow_item_pppoe); + case RTE_FLOW_ITEM_TYPE_GENEVE: + mask_support = (const char *)&dpaa2_flow_item_geneve_mask; + size = sizeof(struct rte_flow_item_geneve); break; default: return -EINVAL; @@ -1716,19 +1590,17 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, static int dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, - enum dpaa2_rx_faf_offset faf_off, - enum dpaa2_flow_dist_type dist_type, - int group, int *recfg) + struct dpaa2_generic_flow *flow, uint32_t faf_bit_off, + enum dpaa2_flow_dist_type dist_type, int group, int *recfg) { - int ret, index, local_cfg = 0; - struct dpaa2_key_extract *extract; + int ret, index, local_cfg = false; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; - uint8_t faf_byte = faf_off / 8; + uint8_t faf_byte = faf_bit_off / 8; - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - extract = &priv->extract.qos_key_extract; - key_profile = &extract->key_profile; + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); @@ -1741,20 +1613,18 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, return -EINVAL; } - local_cfg |= DPAA2_FLOW_QOS_TYPE; + local_cfg = true; } - ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group, + ret = dpaa2_flow_faf_add_rule(priv, flow, faf_bit_off, group, DPAA2_FLOW_QOS_TYPE); if (ret) { DPAA2_PMD_ERR("QoS faf rule set failed"); - return -EINVAL; + return ret; } - } - - if (dist_type & DPAA2_FLOW_FS_TYPE) { - extract = &priv->extract.tc_key_extract[group]; - key_profile = &extract->key_profile; + } else if (dist_type == DPAA2_FLOW_FS_TYPE) { + tbl_profile = &priv->flow_profile.tc_profile[group]; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); @@ -1768,10 +1638,10 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, return -EINVAL; } - local_cfg |= DPAA2_FLOW_FS_TYPE; + local_cfg = true; } - ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group, + ret = dpaa2_flow_faf_add_rule(priv, flow, faf_bit_off, group, DPAA2_FLOW_FS_TYPE); if (ret) { DPAA2_PMD_ERR("FS[%d] faf rule set failed", @@ -1781,29 +1651,29 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, } if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } static int -dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow, +dpaa2_flow_add_pr_extract_rule(struct dpaa2_generic_flow *flow, uint32_t pr_offset, uint32_t pr_size, const void *key, const void *mask, struct dpaa2_dev_priv *priv, int tc_id, int *recfg, enum dpaa2_flow_dist_type dist_type) { - int index, ret, local_cfg = 0; - struct dpaa2_key_extract *key_extract; + int index, ret, local_cfg = false; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; uint32_t pr_field = pr_offset << 16 | pr_size; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - key_profile = &key_extract->key_profile; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_PR_KEY, NET_PROT_NONE, pr_field); @@ -1817,7 +1687,7 @@ dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow, return ret; } - local_cfg |= dist_type; + local_cfg = true; } ret = dpaa2_flow_pr_rule_data_set(flow, key_profile, @@ -1830,31 +1700,31 @@ dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow, } if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } static int -dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow, +dpaa2_flow_add_hdr_extract_rule(struct dpaa2_generic_flow *flow, enum net_prot prot, uint32_t field, const void *key, const void *mask, int size, struct dpaa2_dev_priv *priv, int tc_id, int *recfg, enum dpaa2_flow_dist_type dist_type) { - int index, ret, local_cfg = 0; - struct dpaa2_key_extract *key_extract; + int index, ret, local_cfg = false; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; if (dpaa2_flow_ip_address_extract(prot, field)) return -EINVAL; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - key_profile = &key_extract->key_profile; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_NET_PROT_KEY, prot, field); @@ -1868,7 +1738,7 @@ dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow, return ret; } - local_cfg |= dist_type; + local_cfg = true; } ret = dpaa2_flow_hdr_rule_data_set(flow, key_profile, @@ -1881,44 +1751,57 @@ dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow, } if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } static int -dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow, +dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_generic_flow *flow, enum net_prot prot, uint32_t field, const void *key, const void *mask, int size, struct dpaa2_dev_priv *priv, int tc_id, int *recfg, enum dpaa2_flow_dist_type dist_type) { - int local_cfg = 0, num, ipaddr_extract_len = 0; - struct dpaa2_key_extract *key_extract; + int local_cfg = false, update = 0, ret, pos = 0; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; struct dpkg_profile_cfg *dpkg; - uint8_t *key_addr, *mask_addr; - union ip_addr_extract_rule *ip_addr_data; - union ip_addr_extract_rule *ip_addr_mask; - enum net_prot orig_prot; - uint32_t orig_field; - - if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6) - return -EINVAL; + uint8_t *key_addr, *mask_addr, num; + uint8_t ip_addr_offset = 0; - if (prot == NET_PROT_IPV4 && field != NH_FLD_IPV4_SRC_IP && - field != NH_FLD_IPV4_DST_IP) { + if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6) { + DPAA2_PMD_ERR("%s: Invalid protocol(%d)", + __func__, prot); return -EINVAL; } - if (prot == NET_PROT_IPV6 && field != NH_FLD_IPV6_SRC_IP && - field != NH_FLD_IPV6_DST_IP) { - return -EINVAL; + if (prot == NET_PROT_IPV4) { + if (field != NH_FLD_IPV4_SRC_IP && + field != NH_FLD_IPV4_DST_IP) { + DPAA2_PMD_ERR("%s: Invalid ipv4 filed(%d)", + __func__, field); + return -EINVAL; + } + if (size != sizeof(rte_be32_t)) { + DPAA2_PMD_ERR("%s: Invalid ipv4 address size(%d)", + __func__, size); + return -EINVAL; + } + } else { + if (field != NH_FLD_IPV6_SRC_IP && + field != NH_FLD_IPV6_DST_IP) { + DPAA2_PMD_ERR("%s: Invalid ipv6 filed(%d)", + __func__, field); + return -EINVAL; + } + if (size != NH_FLD_IPV6_ADDR_SIZE) { + DPAA2_PMD_ERR("%s: Invalid ipv6 address size(%d)", + __func__, size); + return -EINVAL; + } } - orig_prot = prot; - orig_field = field; - if (prot == NET_PROT_IPV4 && field == NH_FLD_IPV4_SRC_IP) { prot = NET_PROT_IP; @@ -1941,182 +1824,111 @@ dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow, return -EINVAL; } - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - key_extract = &priv->extract.qos_key_extract; - key_profile = &key_extract->key_profile; - dpkg = &key_extract->dpkg; - num = key_profile->num; - key_addr = flow->qos_key_addr; - mask_addr = flow->qos_mask_addr; - } else { - key_extract = &priv->extract.tc_key_extract[tc_id]; - key_profile = &key_extract->key_profile; - dpkg = &key_extract->dpkg; - num = key_profile->num; - key_addr = flow->fs_key_addr; - mask_addr = flow->fs_mask_addr; - } + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + + key_profile = &tbl_profile->key_profile; + dpkg = &tbl_profile->dpkg; + num = key_profile->num; + key_addr = flow->key_addr; + mask_addr = flow->mask_addr; if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (field == NH_FLD_IP_SRC) - key_profile->ip_addr_type = IP_SRC_EXTRACT; - else - key_profile->ip_addr_type = IP_DST_EXTRACT; - ipaddr_extract_len = size; - - key_profile->ip_addr_extract_pos = num; - if (num > 0) { - key_profile->ip_addr_extract_off = - key_profile->key_offset[num - 1] + - key_profile->key_size[num - 1]; - } else { - key_profile->ip_addr_extract_off = 0; - } - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; - } else if (key_profile->ip_addr_type == IP_SRC_EXTRACT) { - if (field == NH_FLD_IP_SRC) { - ipaddr_extract_len = size; - goto rule_configure; - } - key_profile->ip_addr_type = IP_SRC_DST_EXTRACT; - ipaddr_extract_len = size * 2; - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; - } else if (key_profile->ip_addr_type == IP_DST_EXTRACT) { - if (field == NH_FLD_IP_DST) { - ipaddr_extract_len = size; - goto rule_configure; - } - key_profile->ip_addr_type = IP_DST_SRC_EXTRACT; - ipaddr_extract_len = size * 2; - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; + pos = dpaa2_extract_prev_ip_addr_pos(key_profile); + if (pos >= 0) { + ip_addr_offset = key_profile->key_offset[pos] + + key_profile->key_size[pos]; } - key_profile->num++; - key_profile->prot_field[num].type = DPAA2_NET_PROT_KEY; - dpkg->extracts[num].extract.from_hdr.prot = prot; - dpkg->extracts[num].extract.from_hdr.field = field; - dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD; - dpkg->num_extracts++; + ret = dpaa2_extract_ip_addr_add(field, + key_profile, size, &update, &pos); + if (ret) { + DPAA2_PMD_ERR("Add IP address extract failed(%d)", ret); + return ret; + } + if (pos > 1) { + DPAA2_PMD_ERR("Invalid IP address extract position(%d)", pos); + return -EINVAL; + } + if (update) { + key_profile->num++; + key_profile->prot_field[num].type = DPAA2_NET_PROT_KEY; + key_profile->prot_field[num].prot = prot; + key_profile->prot_field[num].key_field = field; - if (dist_type == DPAA2_FLOW_QOS_TYPE) - local_cfg = DPAA2_FLOW_QOS_TYPE; - else - local_cfg = DPAA2_FLOW_FS_TYPE; - -rule_configure: - key_addr += key_profile->ip_addr_extract_off; - ip_addr_data = (union ip_addr_extract_rule *)key_addr; - mask_addr += key_profile->ip_addr_extract_off; - ip_addr_mask = (union ip_addr_extract_rule *)mask_addr; - - if (orig_prot == NET_PROT_IPV4 && - orig_field == NH_FLD_IPV4_SRC_IP) { - if (key_profile->ip_addr_type == IP_SRC_EXTRACT || - key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) { - memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_src, - key, size); - memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_src, - mask, size); - } else { - memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_src, - key, size); - memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_src, - mask, size); - } - } else if (orig_prot == NET_PROT_IPV4 && - orig_field == NH_FLD_IPV4_DST_IP) { - if (key_profile->ip_addr_type == IP_DST_EXTRACT || - key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) { - memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_dst, - key, size); - memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_dst, - mask, size); - } else { - memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_dst, - key, size); - memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_dst, - mask, size); - } - } else if (orig_prot == NET_PROT_IPV6 && - orig_field == NH_FLD_IPV6_SRC_IP) { - if (key_profile->ip_addr_type == IP_SRC_EXTRACT || - key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) { - memcpy(ip_addr_data->ipv6_sd_addr.ipv6_src, - key, size); - memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_src, - mask, size); - } else { - memcpy(ip_addr_data->ipv6_ds_addr.ipv6_src, - key, size); - memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_src, - mask, size); - } - } else if (orig_prot == NET_PROT_IPV6 && - orig_field == NH_FLD_IPV6_DST_IP) { - if (key_profile->ip_addr_type == IP_DST_EXTRACT || - key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) { - memcpy(ip_addr_data->ipv6_ds_addr.ipv6_dst, - key, size); - memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_dst, - mask, size); - } else { - memcpy(ip_addr_data->ipv6_sd_addr.ipv6_dst, - key, size); - memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_dst, - mask, size); - } + dpkg->extracts[num].type = DPKG_EXTRACT_FROM_HDR; + dpkg->extracts[num].extract.from_hdr.prot = prot; + dpkg->extracts[num].extract.from_hdr.field = field; + dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD; + dpkg->num_extracts++; + + local_cfg = true; } - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - flow->qos_rule_size = - key_profile->ip_addr_extract_off + ipaddr_extract_len; + key_addr += ip_addr_offset; + mask_addr += ip_addr_offset; + + if (pos == 0) { + rte_memcpy(key_addr, key, size); + rte_memcpy(mask_addr, mask, size); } else { - flow->fs_rule_size = - key_profile->ip_addr_extract_off + ipaddr_extract_len; + rte_memcpy(key_addr + size, key, size); + rte_memcpy(mask_addr + size, mask, size); } + flow->rule_size = ip_addr_offset + size * (pos + 1); + if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } +static void dpaa2_flow_hdr_hexdump(char *dump_buf, + const uint8_t *hdr, uint32_t size) +{ + uint32_t i; + + for (i = 0; i < size; i++) + sprintf(&dump_buf[i], "%02x ", hdr[i]); +} + static int -dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_tunnel_eth_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - int *device_configured) + const struct rte_flow_item *pattern, int *extract_cfg, + enum dpaa2_flow_dist_type dist_type) { - int ret, local_cfg = 0; + int ret, local_cfg = false; uint32_t group; const struct rte_flow_item_eth *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; + + if (!pattern->spec) + return 0; group = attr->group; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_eth_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (!spec) - return 0; + pattern->mask : &dpaa2_flow_item_eth_mask; ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ETH); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ethernet failed"); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_eth)); + DPAA2_PMD_WARN("Extract ethernet(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2128,40 +1940,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR0_OFFSET, 1, &spec->src.addr_bytes[0], &mask->src.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[1:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR1_OFFSET, - 2, &spec->src.addr_bytes[1], - &mask->src.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[3:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR3_OFFSET, - 1, &spec->src.addr_bytes[3], - &mask->src.addr_bytes[3], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[4:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR4_OFFSET, - 2, &spec->src.addr_bytes[4], - &mask->src.addr_bytes[4], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - /*SRC[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR0_OFFSET, - 1, &spec->src.addr_bytes[0], - &mask->src.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*SRC[1:2]*/ @@ -2169,7 +1948,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR1_OFFSET, 2, &spec->src.addr_bytes[1], &mask->src.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*SRC[3:1]*/ @@ -2177,7 +1956,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR3_OFFSET, 1, &spec->src.addr_bytes[3], &mask->src.addr_bytes[3], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*SRC[4:2]*/ @@ -2185,7 +1964,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR4_OFFSET, 2, &spec->src.addr_bytes[4], &mask->src.addr_bytes[4], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; } @@ -2197,40 +1976,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR0_OFFSET, 1, &spec->dst.addr_bytes[0], &mask->dst.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[1:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR1_OFFSET, - 1, &spec->dst.addr_bytes[1], - &mask->dst.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[2:3]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR2_OFFSET, - 3, &spec->dst.addr_bytes[2], - &mask->dst.addr_bytes[2], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[5:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR5_OFFSET, - 1, &spec->dst.addr_bytes[5], - &mask->dst.addr_bytes[5], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - /*DST[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR0_OFFSET, - 1, &spec->dst.addr_bytes[0], - &mask->dst.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*DST[1:1]*/ @@ -2238,7 +1984,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR1_OFFSET, 1, &spec->dst.addr_bytes[1], &mask->dst.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*DST[2:3]*/ @@ -2246,7 +1992,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR2_OFFSET, 3, &spec->dst.addr_bytes[2], &mask->dst.addr_bytes[2], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*DST[5:1]*/ @@ -2254,7 +2000,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR5_OFFSET, 1, &spec->dst.addr_bytes[5], &mask->dst.addr_bytes[5], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; } @@ -2264,76 +2010,65 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_pr_extract_rule(flow, DPAA2_VXLAN_IN_TYPE_OFFSET, sizeof(rte_be16_t), &spec->type, &mask->type, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TYPE_OFFSET, - sizeof(rte_be16_t), &spec->type, &mask->type, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_eth_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_eth *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; if (dpaa2_pattern->in_tunnel) { - return dpaa2_configure_flow_tunnel_eth(flow, - dev, attr, pattern, device_configured); + return dpaa2_flow_tunnel_eth_extract_rule_set(flow, + attr, pattern, extract_cfg, + dist_type); } - group = attr->group; - /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_eth_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + pattern->mask : &dpaa2_flow_item_eth_mask; if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ETH_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_MAC_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ETH_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + bit_offset, dist_type, + attr->group, &local_cfg); + if (extract_cfg && !ret) + (*extract_cfg) |= local_cfg; - (*device_configured) |= local_cfg; - return 0; + return ret; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ETH); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ethernet failed"); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_eth)); + DPAA2_PMD_WARN("Extract ethernet(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2343,14 +2078,7 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, NH_FLD_ETH_SA, &spec->src.addr_bytes, &mask->src.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_SA, &spec->src.addr_bytes, - &mask->src.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -2360,14 +2088,7 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, NH_FLD_ETH_DA, &spec->dst.addr_bytes, &mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_DA, &spec->dst.addr_bytes, - &mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -2377,34 +2098,28 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, NH_FLD_ETH_TYPE, &spec->type, &mask->type, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_TYPE, &spec->type, - &mask->type, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_tunnel_vlan_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - int *device_configured) + const struct rte_flow_item *pattern, int *extract_cfg, + enum dpaa2_flow_dist_type dist_type) { - int ret, local_cfg = 0; - uint32_t group; + int ret, local_cfg = false; + uint32_t group, bit_offset; const struct rte_flow_item_vlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; group = attr->group; @@ -2413,33 +2128,30 @@ dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow, mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_VLAN_FRAM, - DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_VLAN_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_VLAN_FRAM, - DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, + attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_VLAN); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of vlan not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_vlan)); + DPAA2_PMD_WARN("Extract vlan(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2450,74 +2162,64 @@ dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_pr_extract_rule(flow, DPAA2_VXLAN_IN_TCI_OFFSET, sizeof(rte_be16_t), &spec->tci, &mask->tci, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TCI_OFFSET, - sizeof(rte_be16_t), &spec->tci, &mask->tci, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_vlan_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_vlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; if (dpaa2_pattern->in_tunnel) { - return dpaa2_configure_flow_tunnel_vlan(flow, - dev, attr, pattern, device_configured); + return dpaa2_flow_tunnel_vlan_extract_rule_set(flow, + attr, pattern, extract_cfg, + dist_type); } - group = attr->group; - /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_VLAN_ID); + if (ret) + return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - if (ret) - return ret; + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; - (*device_configured) |= local_cfg; + if (!spec) { + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_VLAN); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of vlan not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_vlan)); + DPAA2_PMD_WARN("Extract vlan(%s) failed(%d)", + hex_dump, ret); + return ret; } @@ -2527,45 +2229,34 @@ dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN, NH_FLD_VLAN_TCI, &spec->tci, &mask->tci, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN, - NH_FLD_VLAN_TCI, &spec->tci, - &mask->tci, sizeof(rte_be16_t), - priv, group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ipv4_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ipv4 *spec_ipv4 = 0, *mask_ipv4 = 0; const void *key, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; int size; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec_ipv4 = pattern->spec; mask_ipv4 = pattern->mask ? - pattern->mask : &dpaa2_flow_item_ipv4_mask; + pattern->mask : &dpaa2_flow_item_ipv4_mask; if (dpaa2_pattern->in_tunnel) { if (spec_ipv4) { @@ -2573,44 +2264,48 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV4_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_IPV4_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV4_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, + attr->group, &local_cfg); + if (ret) + return ret; } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPV4_ID); if (ret) return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, + attr->group, &local_cfg); if (ret) return ret; if (!spec_ipv4) { - (*device_configured) |= local_cfg; + if (flow->ip_key == NET_PROT_IPV6) { + DPAA2_PMD_ERR("IPv6 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV4; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv4, RTE_FLOW_ITEM_TYPE_IPV4); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of IPv4 not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask_ipv4, + sizeof(struct rte_flow_item_ipv4)); + DPAA2_PMD_WARN("Extract IPv4(%s) failed(%d)", + hex_dump, ret); + return ret; } @@ -2620,20 +2315,11 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, size = sizeof(rte_be32_t); ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IPV4_SRC_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; + flow->ip_src = NET_PROT_IPV4; } if (mask_ipv4->hdr.dst_addr) { @@ -2642,19 +2328,41 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, size = sizeof(rte_be32_t); ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); + NH_FLD_IPV4_DST_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + flow->ip_dst = NET_PROT_IPV4; + } + + if (mask_ipv4->hdr.packet_id) { + key = &spec_ipv4->hdr.packet_id; + mask = &mask_ipv4->hdr.packet_id; + size = sizeof(rte_be16_t); + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, + NH_FLD_IP_ID, key, mask, size, + priv, attr->group, &local_cfg, dist_type); + if (ret) + return ret; + } + + if (mask_ipv4->hdr.fragment_offset) { + key = &spec_ipv4->hdr.fragment_offset; + mask = &mask_ipv4->hdr.fragment_offset; + size = sizeof(rte_be16_t); + + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IP_FRAG_ID); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; + + if (spec_ipv4->hdr.fragment_offset) + DPAA2_PMD_WARN("Unsupport Extract of frag offset"); } if (mask_ipv4->hdr.next_proto_id) { @@ -2663,139 +2371,117 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, size = sizeof(uint8_t); ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IP_PROTO, key, mask, size, priv, attr->group, + &local_cfg, dist_type); if (ret) return ret; } + if (flow->ip_key == NET_PROT_IPV6) { + DPAA2_PMD_ERR("IPv6 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV4; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ipv6_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ipv6 *spec_ipv6 = 0, *mask_ipv6 = 0; const void *key, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0}; int size; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec_ipv6 = pattern->spec; mask_ipv6 = pattern->mask ? pattern->mask : &dpaa2_flow_item_ipv6_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { if (spec_ipv6) { DPAA2_PMD_ERR("Tunnel-IPv6 distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV6_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_IPV6_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV6_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, + attr->group, &local_cfg); + if (ret) + return ret; } - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPV6_ID); if (ret) return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec_ipv6) { - (*device_configured) |= local_cfg; + if (flow->ip_key == NET_PROT_IPV4) { + DPAA2_PMD_ERR("IPv4 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV6; + + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv6, RTE_FLOW_ITEM_TYPE_IPV6); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of IPv6 not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask_ipv6, + sizeof(struct rte_flow_item_ipv6)); + DPAA2_PMD_WARN("Extract IPv6(%s) failed(%d)", + hex_dump, ret); + return ret; } - if (memcmp((const char *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { + if (memcmp((const void *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { key = &spec_ipv6->hdr.src_addr; mask = &mask_ipv6->hdr.src_addr; size = NH_FLD_IPV6_ADDR_SIZE; ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IPV6_SRC_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; + flow->ip_src = NET_PROT_IPV6; } - if (memcmp((const char *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { + if (memcmp((const void *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { key = &spec_ipv6->hdr.dst_addr; mask = &mask_ipv6->hdr.dst_addr; size = NH_FLD_IPV6_ADDR_SIZE; ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IPV6_DST_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; + flow->ip_dst = NET_PROT_IPV6; } if (mask_ipv6->hdr.proto) { @@ -2804,78 +2490,68 @@ dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow, size = sizeof(uint8_t); ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IP_PROTO, key, mask, size, priv, attr->group, + &local_cfg, dist_type); if (ret) return ret; } + if (flow->ip_key == NET_PROT_IPV4) { + DPAA2_PMD_ERR("IPv4 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV6; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_icmp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_icmp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_icmp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-ICMP distribution not support"); return -ENOTSUP; } if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ICMP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_ICMP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ICMP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ICMP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ICMP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_icmp)); + DPAA2_PMD_WARN("Extract ICMP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2884,14 +2560,7 @@ dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type, &mask->hdr.icmp_type, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type, - &mask->hdr.icmp_type, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -2900,90 +2569,75 @@ dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, NH_FLD_ICMP_CODE, &spec->hdr.icmp_code, &mask->hdr.icmp_code, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_CODE, &spec->hdr.icmp_code, - &mask->hdr.icmp_code, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_udp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_udp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_udp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { if (spec) { DPAA2_PMD_ERR("Tunnel-UDP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_UDP_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_UDP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_UDP_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_UDP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_UDP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_UDP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_UDP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of UDP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_udp)); + DPAA2_PMD_ERR("Extract UDP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2992,14 +2646,7 @@ dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port, &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3008,90 +2655,75 @@ dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port, &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_tcp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_tcp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_tcp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { if (spec) { DPAA2_PMD_ERR("Tunnel-TCP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_TCP_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_TCP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_TCP_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_TCP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TCP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_TCP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_TCP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of TCP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_tcp)); + DPAA2_PMD_ERR("Extract TCP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3100,14 +2732,7 @@ dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port, &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3116,76 +2741,64 @@ dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port, &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_esp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_esp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_esp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-ESP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPSEC_ESP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ESP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ESP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_esp)); + DPAA2_PMD_ERR("Extract IPSEC ESP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3194,14 +2807,7 @@ dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi, &mask->hdr.spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi, - &mask->hdr.spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3210,76 +2816,64 @@ dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq, &mask->hdr.seq, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq, - &mask->hdr.seq, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ah_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ah *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_ah_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-AH distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_AH_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPSEC_AH_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_AH_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_AH); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of AH not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_ah)); + DPAA2_PMD_ERR("Extract IPSEC AH(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3288,14 +2882,7 @@ dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH, NH_FLD_IPSEC_AH_SPI, &spec->spi, &mask->spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH, - NH_FLD_IPSEC_AH_SPI, &spec->spi, - &mask->spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3305,63 +2892,58 @@ dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow, return -ENOTSUP; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_sctp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_sctp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_sctp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-SCTP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_SCTP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_SCTP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_SCTP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_SCTP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of SCTP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_sctp)); + DPAA2_PMD_ERR("Extract SCTP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3370,14 +2952,7 @@ dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port, &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3386,80 +2961,63 @@ dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port, &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_gre_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_gre *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_gre_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-GRE distribution not support"); return -ENOTSUP; } if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GRE_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_GRE_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GRE_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } - if (!priv->sp_protocol) { - DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); - return -ENOTSUP; - } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_GRE); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of GRE not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_gre)); + DPAA2_PMD_ERR("Extract GRE(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3468,81 +3026,65 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE, - NH_FLD_GRE_TYPE, &spec->protocol, - &mask->protocol, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE, - NH_FLD_GRE_TYPE, &spec->protocol, - &mask->protocol, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + NH_FLD_GRE_TYPE, &spec->protocol, &mask->protocol, + sizeof(rte_be16_t), priv, attr->group, &local_cfg, dist_type); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_vxlan_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - if (!priv->sp_protocol) { - DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); - return -ENOTSUP; - } - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vxlan_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); return -ENOTSUP; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_VXLAN_ID); + if (ret) + return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; - (*device_configured) |= local_cfg; - return 0; + if (!spec) + goto quit; + + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); + return -ENOTSUP; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_VXLAN); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_vxlan)); + DPAA2_PMD_ERR("Extract vXLAN(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3562,55 +3104,45 @@ dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { ret = dpaa2_flow_add_pr_extract_rule(flow, DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + sizeof(mask->vni), spec->vni, mask->vni, + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; +quit: + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ecpri_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ecpri *spec, *mask; struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; + int extract_nb, i; uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; + union dpaa2_sp_fafe_parse fafe; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; if (!priv->sp_protocol) { - DPAA2_PMD_ERR("ROCEV2 flow is not supported without SP."); + DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); return -ENOTSUP; } - group = attr->group; - /* Parse pattern list to get the matching parameters */ spec = pattern->spec; if (pattern->mask) { @@ -3623,353 +3155,111 @@ dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, mask = &dpaa2_flow_item_ecpri_mask; } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); return -ENOTSUP; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_ECPRI_ID); + if (ret) + return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, + attr->group, &local_cfg); + if (ret) + return ret; - (*device_configured) |= local_cfg; - return 0; - } + if (!spec) + goto quit; ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ECPRI); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_ecpri)); + DPAA2_PMD_ERR("Extract eCPRI(%s) failed(%d)", + hex_dump, ret); return ret; } - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } + memset(&fafe, 0, sizeof(union dpaa2_sp_fafe_parse)); + extract_nb = dpaa2_parser_ecpri_extract(spec, mask, + rule_data, mask_data, extract_size, extract_off, + &fafe, DPAA2_ECPRI_MAX_EXTRACT_NB); + if (extract_nb < 0) { + DPAA2_PMD_ERR("Extract eCPRI from spec/mask failed(%d)", + extract_nb); - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; + return extract_nb; } for (i = 0; i < extract_nb; i++) { ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); + extract_off[i], extract_size[i], + &rule_data[i], &mask_data[i], + priv, attr->group, extract_cfg, + dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; +quit: + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_gtp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_gtp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - if (!priv->sp_protocol) { - DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); - return -ENOTSUP; - } - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_gtp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-GTP distribution not support"); return -ENOTSUP; } if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GTP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_GTP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GTP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_GTP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of GTP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_gtp)); + DPAA2_PMD_ERR("Extract GTP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3978,298 +3268,236 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP, - NH_FLD_GTP_TEID, &spec->teid, - &mask->teid, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP, - NH_FLD_GTP_TEID, &spec->teid, - &mask->teid, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + NH_FLD_GTP_TEID, &spec->teid, &mask->teid, + sizeof(rte_be32_t), priv, attr->group, + &local_cfg, dist_type); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_raw_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_mpls *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_mpls_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + struct dpaa2_dev_priv *priv = flow->priv; + int local_cfg = 0, ret; + struct dpaa2_flow_tbl_profile *tbl_profile; + const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + const struct rte_flow_item_raw *spec = pattern->spec; + const struct rte_flow_item_raw *mask = pattern->mask; - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); - return -ENOTSUP; + /* Need both spec and mask */ + if (!spec || !mask) { + DPAA2_PMD_ERR("spec or mask not present."); + return -EINVAL; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + if (spec->relative) { + /* TBD: relative offset support. + * To support relative offset of previous L3 protocol item, + * extracts should be expanded to identify if the frame is: + * vlan or none-vlan. + * + * To support relative offset of previous L4 protocol item, + * extracts should be expanded to identify if the frame is: + * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6. + */ + DPAA2_PMD_ERR("relative not supported."); + return -EINVAL; + } - (*device_configured) |= local_cfg; - return 0; + if (spec->search) { + DPAA2_PMD_ERR("search not supported."); + return -EINVAL; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_MPLS); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); - return ret; + /* Spec len and mask len should be same */ + if (spec->length != mask->length) { + DPAA2_PMD_ERR("Spec len and mask len mismatch."); + return -EINVAL; } - if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && - !mask->label_tc_s[2]) - return 0; + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[attr->group]; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, - NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, - mask->label_tc_s, sizeof(mask->label_tc_s), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) + ret = dpaa2_flow_extract_add_raw(priv, + spec->offset, spec->length, dist_type, + attr->group, &local_cfg); + if (ret) { + DPAA2_PMD_ERR("QoS Extract RAW add failed(%d).", ret); return ret; + } - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, - NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, - mask->label_tc_s, sizeof(mask->label_tc_s), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + if (dist_type == DPAA2_FLOW_QOS_TYPE || + dist_type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_raw_rule_data_set(flow, + &tbl_profile->key_profile, + spec->offset, spec->length, + spec->pattern, mask->pattern, + dist_type); + if (ret) { + DPAA2_PMD_ERR("QoS RAW rule data set failed(%d)", ret); + return ret; + } + } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_geneve_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_pppoe *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; + uint32_t bit_offset; + const struct rte_flow_item_geneve *spec, *mask; + struct dpaa2_dev_priv *priv = flow->priv; + const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; - group = attr->group; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); + return -ENOTSUP; + } /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_pppoe_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + pattern->mask : &dpaa2_flow_item_geneve_mask; if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + DPAA2_PMD_ERR("Tunnel-GENEVE distribution not support"); return -ENOTSUP; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_PPPOES); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); - return ret; - } - - if (!mask->session_id) - return 0; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, - NH_FLD_PPPOE_SID, &spec->session_id, - &mask->session_id, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_GENEVE_ID); if (ret) return ret; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, - NH_FLD_PPPOE_SID, &spec->session_id, - &mask->session_id, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; - - return 0; -} + if (!spec) + goto quit; -static int -dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - struct dpaa2_dev_priv *priv = dev->data->dev_private; - int local_cfg = 0, ret; - uint32_t group; - struct dpaa2_key_extract *qos_key_extract; - struct dpaa2_key_extract *tc_key_extract; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - const struct rte_flow_item_raw *spec = pattern->spec; - const struct rte_flow_item_raw *mask = pattern->mask; + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_GENEVE); + if (ret) { + dpaa2_flow_hdr_hexdump(hex_dump, (const uint8_t *)mask, + sizeof(struct rte_flow_item_geneve)); + DPAA2_PMD_ERR("Extract GENEVE(%s) failed(%d)", + hex_dump, ret); - /* Need both spec and mask */ - if (!spec || !mask) { - DPAA2_PMD_ERR("spec or mask not present."); - return -EINVAL; + return ret; } - if (spec->relative) { - /* TBD: relative offset support. - * To support relative offset of previous L3 protocol item, - * extracts should be expanded to identify if the frame is: - * vlan or none-vlan. - * - * To support relative offset of previous L4 protocol item, - * extracts should be expanded to identify if the frame is: - * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6. - */ - DPAA2_PMD_ERR("relative not supported."); + if (mask->protocol && mask->protocol != 0xffff) { + DPAA2_PMD_ERR("Not support to extract geneve protocol."); return -EINVAL; } - if (spec->search) { - DPAA2_PMD_ERR("search not supported."); - return -EINVAL; + if (mask->protocol) { + ret = dpaa2_flow_add_pr_extract_rule(flow, + DPAA2_GENEVE_PROTOCOL_OFFSET, + sizeof(mask->protocol), &spec->protocol, + &mask->protocol, priv, attr->group, &local_cfg, + dist_type); + if (ret) + return ret; } - /* Spec len and mask len should be same */ - if (spec->length != mask->length) { - DPAA2_PMD_ERR("Spec len and mask len mismatch."); - return -EINVAL; + if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { + ret = dpaa2_flow_add_pr_extract_rule(flow, + DPAA2_GENEVE_VNI_OFFSET, + sizeof(mask->vni), spec->vni, + mask->vni, + priv, attr->group, &local_cfg, dist_type); + if (ret) + return ret; } - /* Get traffic class index and flow id to be configured */ - group = attr->group; - flow->tc_id = group; - flow->tc_index = attr->priority; - - qos_key_extract = &priv->extract.qos_key_extract; - tc_key_extract = &priv->extract.tc_key_extract[group]; - - ret = dpaa2_flow_extract_add_raw(priv, - spec->offset, spec->length, - DPAA2_FLOW_QOS_TYPE, 0, &local_cfg); - if (ret) { - DPAA2_PMD_ERR("QoS Extract RAW add failed."); - return -EINVAL; - } +quit: + if (extract_cfg) + (*extract_cfg) |= local_cfg; - ret = dpaa2_flow_extract_add_raw(priv, - spec->offset, spec->length, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); - if (ret) { - DPAA2_PMD_ERR("FS[%d] Extract RAW add failed.", - group); - return -EINVAL; - } + return 0; +} - ret = dpaa2_flow_raw_rule_data_set(flow, - &qos_key_extract->key_profile, - spec->offset, spec->length, - spec->pattern, mask->pattern, - DPAA2_FLOW_QOS_TYPE); - if (ret) { - DPAA2_PMD_ERR("QoS RAW rule data set failed"); - return -EINVAL; - } +static inline int +dpaa2_flow_verify_entry(struct dpaa2_dev_priv *priv, + uint16_t tc, uint16_t entry_idx, + enum dpaa2_flow_dist_type dist_type) +{ + struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - ret = dpaa2_flow_raw_rule_data_set(flow, - &tc_key_extract->key_profile, - spec->offset, spec->length, - spec->pattern, mask->pattern, - DPAA2_FLOW_FS_TYPE); - if (ret) { - DPAA2_PMD_ERR("FS RAW rule data set failed"); - return -EINVAL; + while (curr) { + if (dist_type == DPAA2_FLOW_QOS_TYPE && + curr->qos_flow && + curr->qos_flow->entry_index == entry_idx) { + DPAA2_PMD_ERR("Flow QoS.entry[%d] exists", + curr->qos_flow->entry_index); + return -EEXIST; + } + if (dist_type == DPAA2_FLOW_FS_TYPE && + curr->fs_flow && curr->fs_flow->tc_id == tc && + curr->fs_flow->entry_index == entry_idx) { + DPAA2_PMD_ERR("Flow TC[%d].entry[%d] exists", + tc, curr->fs_flow->entry_index); + return -EEXIST; + } + curr = LIST_NEXT(curr, next); } - (*device_configured) |= local_cfg; - return 0; } static inline int -dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv, - const struct rte_flow_attr *attr) +dpaa2_flow_acquire_entry_idx(struct dpaa2_dev_priv *priv, + uint16_t idx, enum dpaa2_flow_dist_type dist_type, + uint8_t group) { - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); + int occupied = -1; + uint16_t max_entries; + struct dpaa2_flow_tbl_profile *tbl_profile; - while (curr) { - if (curr->tc_id == attr->group && - curr->tc_index == attr->priority) { - DPAA2_PMD_ERR("Flow(TC[%d].entry[%d] exists", - attr->group, attr->priority); + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + max_entries = priv->qos_entries; + } else { + tbl_profile = &priv->flow_profile.tc_profile[group]; + max_entries = priv->fs_entries; + } - return -EINVAL; + if (!dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx)) + return idx; + + idx = 0; + while (idx < max_entries) { + if (!dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx)) { + occupied = idx; + break; } - curr = LIST_NEXT(curr, next); + idx++; } - return 0; + return occupied; } static inline struct rte_eth_dev * @@ -4306,7 +3534,7 @@ dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv, } static inline int -dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, +dpaa2_flow_verify_fs_action(struct dpaa2_dev_priv *priv, const struct rte_flow_attr *attr, const struct rte_flow_action actions[]) { @@ -4332,46 +3560,51 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, rxq->tc_index, rxq->flow_id, attr->group); - return -ENOTSUP; + return -EINVAL; } break; case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: if (!dpaa2_flow_redirect_dev(priv, &actions[j])) { DPAA2_PMD_ERR("Invalid port id of action"); - return -ENOTSUP; + return -EINVAL; } break; case RTE_FLOW_ACTION_TYPE_RSS: - rss_conf = (const struct rte_flow_action_rss *) - (actions[j].conf); + rss_conf = actions[j].conf; if (rss_conf->queue_num > priv->dist_queues) { DPAA2_PMD_ERR("RSS number too large"); - return -ENOTSUP; + return -EINVAL; } - for (i = 0; i < (int)rss_conf->queue_num; i++) { - if (rss_conf->queue[i] >= priv->nb_rx_queues) { - DPAA2_PMD_ERR("RSS queue not in range"); - return -ENOTSUP; - } - rxq = priv->rx_vq[rss_conf->queue[i]]; - if (rxq->tc_index != attr->group) { - DPAA2_PMD_ERR("RSS queue not in group"); - return -ENOTSUP; + if (rss_conf->queue) { + for (i = 0; i < (int)rss_conf->queue_num; i++) { + if (rss_conf->queue[i] >= priv->nb_rx_queues) { + DPAA2_PMD_ERR("RSS queue not in range"); + return -EINVAL; + } + rxq = priv->rx_vq[rss_conf->queue[i]]; + if (rxq->tc_index != attr->group) { + DPAA2_PMD_ERR("RSS queue not in group"); + return -EINVAL; + } } } break; case RTE_FLOW_ACTION_TYPE_PF: - /* Skip this action, have to add for vxlan */ + /* Skip this action, have to add for vxlan*/ case RTE_FLOW_ACTION_TYPE_DROP: break; + case RTE_FLOW_ACTION_TYPE_METER_MARK: + break; + case RTE_FLOW_ACTION_TYPE_METER: + break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; break; default: DPAA2_PMD_ERR("Invalid action type"); - return -ENOTSUP; + return -EINVAL; } j++; } @@ -4379,40 +3612,74 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, return 0; } +static struct dpaa2_queue * +dpaa2_flow_queue_action_to_queue(struct dpaa2_dev_priv *priv, + uint8_t tc_id, uint16_t queue_id) +{ + struct dpaa2_queue *dest_q; + + if (queue_id >= MAX_RX_QUEUES || + !priv->rx_vq[queue_id]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", queue_id); + + return NULL; + } + dest_q = priv->rx_vq[queue_id]; + if (tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + queue_id, + dest_q->tc_index, dest_q->flow_id, + tc_id); + + return NULL; + } + + return dest_q; +} + static int -dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, +dpaa2_flow_fs_action_config(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow, const struct rte_flow_action *rte_action) { + struct rte_dpaa2_device *dpaa2_dev; struct rte_eth_dev *dest_dev; struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; uint64_t flc = 0; - - memset(&flow->fs_action_cfg, 0, - sizeof(struct dpni_fs_action_cfg)); - flow->action_type = rte_action->type; - - if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { - dest_queue = rte_action->conf; - if (dest_queue->index >= MAX_RX_QUEUES || - !priv->rx_vq[dest_queue->index]) { - DPAA2_PMD_ERR("Invalid FSQ index(%d)", - dest_queue->index); - + uint16_t num_tokens; + struct dpaa2_dev_flow_fs_action *fs_action; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + fs_action = &flow->flow_action.fs_action; + if (fs_action->action_type != RTE_FLOW_ACTION_TYPE_END) { + if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV && + (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || + fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR)) { + if (rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_ID && + rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR) { + DPAA2_PMD_ERR("Redirect action can't mix with other action(%d)", + rte_action->type); + return -EINVAL; + } + } else { + DPAA2_PMD_ERR("Single action support only with action(%d)", + fs_action->action_type); return -EINVAL; } - dest_q = priv->rx_vq[dest_queue->index]; - if (flow->tc_id != dest_q->tc_index) { - DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", - dest_queue->index, - dest_q->tc_index, dest_q->flow_id, - flow->tc_id); + } + fs_action->action_type = rte_action->type; + if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { + dest_queue = rte_action->conf; + dest_q = dpaa2_flow_queue_action_to_queue(priv, + flow->tc_id, dest_queue->index); + if (!dest_q) return -EINVAL; - } - flow->fs_action_cfg.options = + + fs_action->fs_action_cfg.options = DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; if (dest_q->data_stashing_off) { @@ -4430,10 +3697,10 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; - flow->fs_action_cfg.flc = flc; - flow->fs_action_cfg.flow_id = dest_q->flow_id; - } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || - flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { + fs_action->fs_action_cfg.flc = flc; + fs_action->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || + fs_action->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { dest_dev = dpaa2_flow_redirect_dev(priv, rte_action); if (!dest_dev) { DPAA2_PMD_ERR("Invalid device to redirect"); @@ -4441,15 +3708,34 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } dest_priv = dest_dev->data->dev_private; - dest_q = dest_priv->tx_vq[0]; - flow->fs_action_cfg.options = - DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; - flow->fs_action_cfg.num_tokens = 1; - flow->fs_action_cfg.redir_tokens[0] = - dest_priv->token; - flow->fs_action_cfg.flow_id = dest_q->flow_id; - } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { - flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; + num_tokens = fs_action->fs_action_cfg.num_tokens; + if (num_tokens >= DPNI_FS_REDIR_MAX_NUM) + return -EINVAL; + fs_action->fs_action_cfg.redir_tokens[num_tokens] = dest_priv->token; + strlcpy(fs_action->dst_name[num_tokens], + dest_priv->eth_dev->data->name, + sizeof(fs_action->dst_name[num_tokens])); + fs_action->fs_action_cfg.num_tokens++; + if (fs_action->fs_action_cfg.num_tokens > 1) { + if (!(priv->options & DPNI_OPT_V8_HAS_REPLICATION)) { + DPAA2_PMD_ERR("0x%08x missed in DPNI creating options(0x%08x)", + DPNI_OPT_V8_HAS_REPLICATION, priv->options); + return -ENOTSUP; + } + fs_action->fs_action_cfg.options = + DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX; + } else { + fs_action->fs_action_cfg.options = + DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; + } + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + fs_action->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_RSS) { + /** Do nothing...*/ + } else { + DPAA2_PMD_ERR("Flow action(%d) not supported!", + fs_action->action_type); + return -ENOTSUP; } return 0; @@ -4477,41 +3763,104 @@ dpaa2_flow_clear_fs_table(struct dpaa2_dev_priv *priv, uint8_t tc_id) { struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - int need_clear = 0, ret; + int fs_num = 0, ret, rss_num = 0; struct fsl_mc_io *dpni = priv->hw; while (curr) { - if (curr->tc_id == tc_id) { - need_clear = 1; - break; + if (curr->fs_flow && curr->fs_flow->tc_id == tc_id) { + if (curr->fs_flow->is_rss) + rss_num++; + else + fs_num++; } curr = LIST_NEXT(curr, next); } - if (need_clear) { + if (rss_num > 1) { + DPAA2_PMD_ERR("TC[%d] should have one RSS flow at most!", + tc_id); + return -EINVAL; + } + if (rss_num && fs_num) { + DPAA2_PMD_ERR("TC[%d] has RSS flow and %d FS flow(s)!", + tc_id, fs_num); + return -EINVAL; + } + + if (fs_num) { ret = dpni_clear_fs_entries(dpni, CMD_PRI_LOW, priv->token, tc_id); if (ret) { DPAA2_PMD_ERR("TC[%d] clear failed", tc_id); return ret; } + priv->flow_profile.tc_profile[tc_id].entry_num = 0; + memset(priv->flow_profile.tc_profile[tc_id].entry_map, + 0, priv->fs_entries); + } + + return 0; +} + +static int +dpaa2_flow_fs_table_set_default(struct dpaa2_dev_priv *priv, + uint8_t tc_id, int discard, uint16_t default_queue) +{ + int ret; + struct rte_dpaa2_device *dpaa2_dev; + struct dpni_rx_dist_cfg *tc_cfg; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_queue *queue; + char mc_rev[1024]; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", + RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + if (!tbl_profile->dpkg.num_extracts && + dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + DPAA2_PMD_DEBUG("%s can't set miss action of FS table indepentently.", + mc_rev); + return 0; + } + tc_cfg = &tbl_profile->tc_cfg; + tc_cfg->enable = true; + if (discard) { + tbl_profile->default_drop = true; + tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP; + } else { + queue = dpaa2_flow_queue_action_to_queue(priv, tc_id, default_queue); + if (!queue) + return -EINVAL; + tbl_profile->default_drop = false; + tbl_profile->default_queue.index = default_queue; + tc_cfg->fs_miss_flow_id = queue->flow_id; + } + ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("%s: Failed(%d) to set default action of TC[%d]", + __func__, ret, tc_id); + return ret; } return 0; } static int -dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, - uint8_t tc_id, uint16_t dist_size, int rss_dist) +dpaa2_flow_fs_rss_table_config(struct dpaa2_dev_priv *priv, + uint8_t tc_id, int rss_dist) { - struct dpaa2_key_extract *tc_extract; + struct dpaa2_flow_tbl_profile *tbl_profile; uint8_t *key_cfg_buf; - uint64_t key_cfg_iova; int ret; - struct dpni_rx_dist_cfg tc_cfg; + struct dpni_rx_dist_cfg *tc_cfg; struct fsl_mc_io *dpni = priv->hw; uint16_t entry_size; uint16_t key_max_size; + struct dpaa2_queue *queue; ret = dpaa2_flow_clear_fs_table(priv, tc_id); if (ret < 0) { @@ -4519,38 +3868,30 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return ret; } - tc_extract = &priv->extract.tc_key_extract[tc_id]; - key_cfg_buf = priv->extract.tc_extract_param[tc_id]; - key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf, - DPAA2_EXTRACT_PARAM_MAX_SIZE); - if (key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, key_cfg_buf); + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + if (!tbl_profile->dpkg.num_extracts) + return 0; - return -ENOBUFS; - } + key_cfg_buf = priv->flow_profile.tc_profile[tc_id].extract_param; - key_max_size = tc_extract->key_profile.key_max_size; + key_max_size = tbl_profile->key_profile.key_max_size; entry_size = dpaa2_flow_entry_size(key_max_size); - dpaa2_flow_fs_extracts_log(priv, tc_id); - ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, + dpaa2_flow_extracts_log(priv, "Configure", tc_id); + ret = dpkg_prepare_key_cfg(&tbl_profile->dpkg, key_cfg_buf); if (ret < 0) { DPAA2_PMD_ERR("TC[%d] prepare key failed", tc_id); return ret; } - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - tc_cfg.dist_size = dist_size; - tc_cfg.key_cfg_iova = key_cfg_iova; + tc_cfg = &tbl_profile->tc_cfg; if (rss_dist) - tc_cfg.enable = true; + tc_cfg->enable = true; else - tc_cfg.enable = false; - tc_cfg.tc = tc_id; + tc_cfg->enable = false; ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, - priv->token, &tc_cfg); + priv->token, tc_cfg); if (ret < 0) { if (rss_dist) { DPAA2_PMD_ERR("RSS TC[%d] set failed", @@ -4563,13 +3904,27 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return ret; } - if (rss_dist) - return 0; + if (rss_dist) { + tbl_profile->is_rss = true; + goto successful_config; + } - tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = priv->default_flow; - ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, - priv->token, &tc_cfg); + tbl_profile->is_rss = false; + + tc_cfg->enable = true; + if (tbl_profile->default_drop) { + tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP; + } else { + queue = dpaa2_flow_queue_action_to_queue(priv, tc_id, + tbl_profile->default_queue.index); + if (!queue) { + DPAA2_PMD_ERR("TC[%d] invalid default queue(%d)", + tc_id, tbl_profile->default_queue.index); + return -EINVAL; + } + tc_cfg->fs_miss_flow_id = queue->flow_id; + } + ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg); if (ret < 0) { DPAA2_PMD_ERR("TC[%d] FS configured failed", tc_id); return ret; @@ -4580,74 +3935,145 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, if (ret) return ret; +successful_config: + tbl_profile->enabled = true; + + return 0; +} + +static int +dpaa2_flow_qos_table_set_default(struct dpaa2_dev_priv *priv, + int discard, uint8_t default_tc, uint16_t default_flow) +{ + int ret; + struct rte_dpaa2_device *dpaa2_dev; + struct dpni_qos_tbl_cfg qos_cfg; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + char mc_rev[1024]; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + tbl_profile = &priv->flow_profile.qos_profile; + snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", + RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + if (!tbl_profile->dpkg.num_extracts && + dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + DPAA2_PMD_DEBUG("%s can't set miss action of QoS table indepentently.", + mc_rev); + return 0; + } + if (default_flow < priv->dist_queues && + dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) { + DPAA2_PMD_WARN("%s can't direct miss traffic to TC%d-flow%d by QoS table only.", + mc_rev, default_tc, default_flow); + return 0; + } + + rte_memcpy(&qos_cfg, &tbl_profile->qos_cfg, sizeof(struct dpni_qos_tbl_cfg)); + qos_cfg.key_cfg_iova = 0; + qos_cfg.default_tc = default_tc; + qos_cfg.default_flow_id = default_flow; + qos_cfg.discard_on_miss = discard ? true : false; + qos_cfg.set_default_flow_id = default_flow < priv->dist_queues ? true : false; + + ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, &qos_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("%s: Failed(%d) to set default action of QoS", + __func__, ret); + return ret; + } + if (discard) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_jump.group = default_tc; + } + rte_memcpy(&tbl_profile->qos_cfg.discard_on_miss, + &qos_cfg.discard_on_miss, + sizeof(struct dpni_qos_tbl_cfg) - + offsetof(struct dpni_qos_tbl_cfg, discard_on_miss)); + return 0; } static int -dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, +dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, int rss_dist) { - struct dpaa2_key_extract *qos_extract; + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_flow_tbl_profile *tbl_profile; uint8_t *key_cfg_buf; - uint64_t key_cfg_iova; int ret; - struct dpni_qos_tbl_cfg qos_cfg; + struct dpni_qos_tbl_cfg *qos_cfg; struct fsl_mc_io *dpni = priv->hw; uint16_t entry_size; uint16_t key_max_size; + struct dpaa2_dev_flow *flow; if (!rss_dist && priv->num_rx_tc <= 1) { /* QoS table is effecitive for FS multiple TCs or RSS.*/ return 0; } - if (LIST_FIRST(&priv->flows)) { + flow = LIST_FIRST(&priv->flows); + while (flow) { + if (!flow->qos_flow) { + flow = LIST_NEXT(flow, next); + continue; + } + /** Clear existing QoS table if there is qos flow configured.*/ ret = dpni_clear_qos_table(dpni, CMD_PRI_LOW, priv->token); if (ret < 0) { - DPAA2_PMD_ERR("QoS table clear failed"); + DPAA2_PMD_ERR("QoS table clear failed(%d)", ret); return ret; } + priv->flow_profile.qos_profile.entry_num = 0; + memset(priv->flow_profile.qos_profile.entry_map, + 0, priv->qos_entries); + break; } - qos_extract = &priv->extract.qos_key_extract; - key_cfg_buf = priv->extract.qos_extract_param; - key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf, - DPAA2_EXTRACT_PARAM_MAX_SIZE); - if (key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, key_cfg_buf); + tbl_profile = &priv->flow_profile.qos_profile; + if (!tbl_profile->dpkg.num_extracts) + return 0; - return -ENOBUFS; - } + key_cfg_buf = priv->flow_profile.qos_profile.extract_param; - key_max_size = qos_extract->key_profile.key_max_size; + key_max_size = tbl_profile->key_profile.key_max_size; entry_size = dpaa2_flow_entry_size(key_max_size); - dpaa2_flow_qos_extracts_log(priv); + dpaa2_flow_extracts_log(priv, "Configure", MAX_TCS); - ret = dpkg_prepare_key_cfg(&qos_extract->dpkg, + ret = dpkg_prepare_key_cfg(&tbl_profile->dpkg, key_cfg_buf); if (ret < 0) { DPAA2_PMD_ERR("QoS prepare extract failed"); return ret; } - memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg)); - qos_cfg.keep_entries = true; - qos_cfg.key_cfg_iova = key_cfg_iova; + qos_cfg = &tbl_profile->qos_cfg; if (rss_dist) { - qos_cfg.discard_on_miss = true; + qos_cfg->discard_on_miss = true; } else { - qos_cfg.discard_on_miss = false; - qos_cfg.default_tc = 0; + qos_cfg->default_tc = tbl_profile->default_jump.group; + if (tbl_profile->default_drop) + qos_cfg->discard_on_miss = true; + else + qos_cfg->discard_on_miss = false; } - ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, - priv->token, &qos_cfg); + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + if (dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) + ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, priv->token, qos_cfg); + else + ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, qos_cfg); if (ret < 0) { - DPAA2_PMD_ERR("QoS table set failed"); + DPAA2_PMD_ERR("QoS table set failed(%d)", ret); return ret; } + tbl_profile->enabled = true; ret = dpaa2_flow_rule_add_all(priv, DPAA2_FLOW_QOS_TYPE, entry_size, 0); @@ -4697,207 +4123,468 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], } static int -dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) +dpaa2_flow_table_update(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type dist_type, uint8_t tc_id, int is_rss) { - const struct rte_flow_action_rss *rss_conf; - int is_keycfg_configured = 0, end_of_list = 0; - int ret = 0, i = 0, j = 0; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - uint16_t dist_size, key_size; - struct dpaa2_key_extract *qos_key_extract; - struct dpaa2_key_extract *tc_key_extract; - struct rte_dpaa2_flow_item *dpaa2_pattern = NULL; - - ret = dpaa2_flow_verify_attr(priv, attr); - if (ret) - return ret; + int ret; - ret = dpaa2_flow_verify_action(priv, attr, actions); - if (ret) - return ret; + if (dist_type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_fs_rss_table_config(priv, tc_id, is_rss); + if (ret) + return ret; + } else if (dist_type == DPAA2_FLOW_QOS_TYPE) { + ret = dpaa2_flow_qos_table_config(priv, false); + if (ret) + return ret; + } else { + DPAA2_PMD_ERR("Invalid dist type(%d)!", dist_type); + return -EINVAL; + } - ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, - priv->sp_protocol); - if (ret) - return ret; + return 0; +} - /* Parse pattern list to get the matching parameters */ - while (!end_of_list) { - switch (pattern[i].type) { +static int +dpaa2_flow_action_meter_mark_init(struct dpaa2_dev_priv *priv, + uint32_t mtr_id, struct rte_flow_action_meter_mark *meter_mark) +{ + struct dpaa2_dev_meter *meter; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + int found = 0; + + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->meter_id == mtr_id) { + found = 1; + break; + } + meter = LIST_NEXT(meter, next); + } + + if (!found) { + DPAA2_PMD_ERR("Meter ID(%d) is not found!", mtr_id); + return -ENXIO; + } + + found = 0; + profile = LIST_FIRST(&priv->profiles); + while (profile) { + if (profile->profile_id == meter->profile_id) { + found = 1; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + DPAA2_PMD_ERR("Meter ID(%d)'s profile(%d) not exist!", + mtr_id, meter->profile_id); + return -ENXIO; + } + + found = 0; + policy = LIST_FIRST(&priv->policies); + while (policy) { + if (policy->policy_id == meter->policy_id) { + found = 1; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + /** Option.*/ + DPAA2_PMD_WARN("Meter ID(%d)'s policy(%d) not exist!", + mtr_id, meter->policy_id); + policy = NULL; + } + + meter_mark->profile = (void *)profile; + meter_mark->policy = (void *)policy; + meter_mark->color_mode = 1; + + return 0; +} + +static int +dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, + uint8_t tc_id, const struct rte_flow_action_meter_mark *meter_mark) +{ + struct rte_dpaa2_device *dpaa2_dev; + struct dpni_rx_tc_policing_cfg policing_cfg = {0}; + const struct dpaa2_dev_meter_profile *dpaa2_profile; + const struct dpaa2_dev_meter_policy *dpaa2_policy = NULL; + int ret; + + if (!(priv->options & DPNI_OPT_HAS_POLICING)) { + DPAA2_PMD_ERR("POLICING(0x%08x) was not added in DPNI creating options(0x%08x)", + DPNI_OPT_HAS_POLICING, priv->options); + return -ENOTSUP; + } + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + dpaa2_profile = (void *)meter_mark->profile; + if (!dpaa2_profile) { + DPAA2_PMD_ERR("Meter profile not specified!"); + return -EINVAL; + } + + /** Blind as default.*/ + policing_cfg.options = 0; + if (meter_mark->color_mode) + policing_cfg.options = DPNI_POLICER_OPT_COLOR_AWARE; + if (meter_mark->policy) + dpaa2_policy = (void *)meter_mark->policy; + if (dpaa2_policy && dpaa2_policy->red_drop) { + policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + } else if (!dpaa2_policy) { + /** Default: Red is discarded if no policy specified.*/ + policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + } + + if (priv->flow_profile.mtr_flow[tc_id]) { + /** Update existing policer.*/ + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + policing_cfg.options |= DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS; + if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV) + DPAA2_PMD_WARN("The existing policer's counters will be cleaned."); + } + + policing_cfg.mode = dpaa2_profile->mode; + if (policing_cfg.mode < DPNI_POLICER_MODE_NONE || + policing_cfg.mode > DPNI_POLICER_MODE_RFC_4115) { + DPAA2_PMD_ERR("Invalid policer mode(%d)", + policing_cfg.mode); + return -EINVAL; + } + policing_cfg.units = dpaa2_profile->policer_unit; + if (policing_cfg.units < DPNI_POLICER_UNIT_BYTES_L3 || + policing_cfg.units > DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS) { + DPAA2_PMD_ERR("Invalid policer units(%d)", + policing_cfg.units); + return -EINVAL; + } + policing_cfg.cir = dpaa2_profile->cir; + policing_cfg.cbs = dpaa2_profile->cbs; + policing_cfg.eir = dpaa2_profile->pir; + policing_cfg.ebs = dpaa2_profile->pbs; + + if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &policing_cfg); + } else { + ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &policing_cfg); + } + DPAA2_PMD_INFO("%s RX TC%d policer configure %s.", + priv->eth_dev->data->name, tc_id, + ret ? "failed" : "successfully"); + if (!ret) + priv->flow_profile.tc_mtr_profile[tc_id] = (void *)meter_mark->profile; + + return ret; +} + +static int +dpaa2_flow_action_single_type_check(const struct rte_flow_action actions[], + enum rte_flow_action_type type) +{ + if (actions[0].type == type && + actions[1].type == RTE_FLOW_ACTION_TYPE_END) + return true; + + return false; +} + +static int +dpaa2_flow_qos_action_update(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow, + const struct rte_flow_action actions[], int new_flow) +{ + int end_of_list = 0, ret = 0, i = 0, set_jump = 0; + struct dpaa2_dev_flow_qos_action *qos_action; + + RTE_SET_USED(priv); + qos_action = &flow->flow_action.qos_action; + + while (!end_of_list) { + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_JUMP: + qos_action->action_jump_type = actions[i].type; + rte_memcpy(&qos_action->action_jump_cfg, actions[i].conf, + sizeof(struct rte_flow_action_jump)); + set_jump++; + break; + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_ERR("Invalid action[%d]'s type(%d)", + i, actions[i].type); + ret = -ENOTSUP; + goto end_action_set; + } + i++; + } + +end_action_set: + if (!set_jump && !ret && new_flow) + return -EINVAL; + + return ret; +} + +static int +dpaa2_flow_fs_action_update(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *fs_flow, + const struct rte_flow_action actions[]) +{ + int end_of_list = 0, ret = 0, i = 0; + const struct rte_flow_action_meter *meter; + struct rte_flow_action_meter_mark meter_mark; + union dpaa2_dev_flow_action flow_action_rollback; + + rte_memcpy(&flow_action_rollback, &fs_flow->flow_action, + sizeof(union dpaa2_dev_flow_action)); + memset(&fs_flow->flow_action, 0, sizeof(union dpaa2_dev_flow_action)); + + while (!end_of_list) { + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: + case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: + case RTE_FLOW_ACTION_TYPE_RSS: + ret = dpaa2_flow_fs_action_config(priv, fs_flow, &actions[i]); + if (ret) + goto end_action_set; + + break; + case RTE_FLOW_ACTION_TYPE_METER_MARK: + rte_memcpy(&meter_mark, actions[i].conf, + sizeof(meter_mark)); + ret = dpaa2_flow_set_police_action(priv, + fs_flow->tc_id, &meter_mark); + if (ret) + goto end_action_set; + break; + case RTE_FLOW_ACTION_TYPE_METER: + meter = actions[i].conf; + ret = dpaa2_flow_action_meter_mark_init(priv, + meter->mtr_id, &meter_mark); + if (ret) + goto end_action_set; + ret = dpaa2_flow_set_police_action(priv, + fs_flow->tc_id, &meter_mark); + if (ret) + goto end_action_set; + + break; + case RTE_FLOW_ACTION_TYPE_PF: + /* Skip this action, have to add for vxlan*/ + break; + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_ERR("Invalid action[%d]'s type(%d)", + i, actions[i].type); + ret = -ENOTSUP; + goto end_action_set; + } + i++; + } + +end_action_set: + if (ret || i < 1) { + rte_memcpy(&fs_flow->flow_action, &flow_action_rollback, + sizeof(union dpaa2_dev_flow_action)); + } + if (ret) + return ret; + + if (i < 1) { + DPAA2_PMD_ERR("No action is set!"); + return -EINVAL; + } + if (i > 2) { + DPAA2_PMD_WARN("Only last of %d actions is applied", + i - 1); + } + + return 0; +} + +static int +dpaa2_flow_generic_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], int is_rss, + enum dpaa2_flow_dist_type dist_type, int update) +{ + int extract_cfg = 0, end_of_list = 0; + int ret = 0, i = 0; + struct dpaa2_dev_priv *priv = flow->priv; + uint16_t key_size; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct rte_dpaa2_flow_item *dpaa2_pattern = NULL; + + ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, + priv->sp_protocol); + if (ret) + return ret; + + flow->ip_key = NET_PROT_NONE; + flow->ip_src = NET_PROT_NONE; + flow->ip_dst = NET_PROT_NONE; + + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[attr->group]; + + if (is_rss || (!is_rss && tbl_profile->is_rss)) { + RTE_ASSERT(dist_type == DPAA2_FLOW_FS_TYPE); + if (!update) { + dpaa2_flow_clean(priv->eth_dev, attr->group); + tbl_profile->rss_flow = NULL; + } + if (!is_rss) + tbl_profile->tc_cfg.dist_size = priv->dist_queues; + memset(&tbl_profile->dpkg, 0, + sizeof(struct dpkg_profile_cfg)); + memset(&tbl_profile->key_profile, 0, + sizeof(struct dpaa2_key_profile)); + } + + /* Parse pattern list to get the matching parameters */ + while (!end_of_list) { + switch (pattern[i].type) { case RTE_FLOW_ITEM_TYPE_ETH: - ret = dpaa2_configure_flow_eth(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_eth_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("ETH flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_VLAN: - ret = dpaa2_configure_flow_vlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_vlan_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("vLan flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_IPV4: - ret = dpaa2_configure_flow_ipv4(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ipv4_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("IPV4 flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_IPV6: - ret = dpaa2_configure_flow_ipv6(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ipv6_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("IPV6 flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_ICMP: - ret = dpaa2_configure_flow_icmp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_icmp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("ICMP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_UDP: - ret = dpaa2_configure_flow_udp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_udp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("UDP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_TCP: - ret = dpaa2_configure_flow_tcp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_tcp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("TCP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_SCTP: - ret = dpaa2_configure_flow_sctp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_sctp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("SCTP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_ESP: - ret = dpaa2_configure_flow_esp(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_esp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("ESP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_AH: - ret = dpaa2_configure_flow_ah(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ah_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("AH flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_GRE: - ret = dpaa2_configure_flow_gre(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_gre_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("GRE flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_vxlan_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ecpri_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_GTP: - ret = dpaa2_configure_flow_gtp(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_gtp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("GTP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_MPLS: - ret = dpaa2_configure_flow_mpls(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("MPLS flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; - case RTE_FLOW_ITEM_TYPE_PPPOES: - ret = dpaa2_configure_flow_pppoe(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + case RTE_FLOW_ITEM_TYPE_GENEVE: + ret = dpaa2_flow_geneve_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { - DPAA2_PMD_ERR("PPPoE flow config failed!"); - goto end_flow_set; + DPAA2_PMD_ERR("GENEVE flow config failed!"); + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_RAW: - ret = dpaa2_configure_flow_raw(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_raw_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("RAW flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_END: @@ -4907,164 +4594,104 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, DPAA2_PMD_ERR("Invalid flow item[%d] type(%d)", i, pattern[i].type); ret = -ENOTSUP; - break; + goto end_extract_set; } i++; } - qos_key_extract = &priv->extract.qos_key_extract; - key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); - - tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; - key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); - - /* Let's parse action on matching traffic */ - end_of_list = 0; - while (!end_of_list) { - switch (actions[j].type) { - case RTE_FLOW_ACTION_TYPE_QUEUE: - case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: - case RTE_FLOW_ACTION_TYPE_PORT_ID: - case RTE_FLOW_ACTION_TYPE_DROP: - ret = dpaa2_configure_flow_fs_action(priv, flow, - &actions[j]); - if (ret) - goto end_flow_set; - - /* Configure FS table first*/ - dist_size = priv->nb_rx_queues / priv->num_rx_tc; - if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_configure_fs_rss_table(priv, - flow->tc_id, - dist_size, - false); - if (ret) - goto end_flow_set; - } - - /* Configure QoS table then.*/ - if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_configure_qos_table(priv, false); - if (ret) - goto end_flow_set; - } - - if (priv->num_rx_tc > 1) { - ret = dpaa2_flow_add_qos_rule(priv, flow); - if (ret) - goto end_flow_set; - } + key_size = tbl_profile->key_profile.key_max_size; + flow->rule_cfg.key_size = dpaa2_flow_entry_size(key_size); - if (flow->tc_index >= priv->fs_entries) { - DPAA2_PMD_ERR("FS table with %d entries full", - priv->fs_entries); - return -1; - } + if (!extract_cfg) + goto end_extract_set; - ret = dpaa2_flow_add_fs_rule(priv, flow); - if (ret) - goto end_flow_set; + ret = dpaa2_flow_table_update(priv, dist_type, attr->group, is_rss); - break; - case RTE_FLOW_ACTION_TYPE_RSS: - rss_conf = actions[j].conf; - flow->action_type = RTE_FLOW_ACTION_TYPE_RSS; - - ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types, - &tc_key_extract->dpkg); - if (ret < 0) { - DPAA2_PMD_ERR("TC[%d] distset RSS failed", - flow->tc_id); - goto end_flow_set; - } +end_extract_set: + if (dpaa2_pattern) + rte_free(dpaa2_pattern); - dist_size = rss_conf->queue_num; - if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_configure_fs_rss_table(priv, - flow->tc_id, - dist_size, - true); - if (ret) - goto end_flow_set; - } + return ret; +} - if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_configure_qos_table(priv, true); - if (ret) - goto end_flow_set; - } +static inline int +dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv, + const struct rte_flow_attr *attr, uint32_t *pgroup_type, + uint32_t *pgroup_id) +{ + int ret = 0; + uint32_t group_id, group_type; - ret = dpaa2_flow_add_qos_rule(priv, flow); - if (ret) - goto end_flow_set; + group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr->group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group); + if (group_id >= priv->num_rx_tc && + group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + group_type = RTE_DPAA2_QOS_GROUP_FLOW; + group_id = DPAA2_FLOW_QOS_GROUP_ID; + } - ret = dpaa2_flow_add_fs_rule(priv, flow); - if (ret) - goto end_flow_set; + if (group_type == RTE_DPAA2_FS_GROUP_FLOW && !priv->fs_entries) { + DPAA2_PMD_ERR("No FS table created to support FS flow!"); + ret = -EINVAL; + goto complete_verify; + } - break; - case RTE_FLOW_ACTION_TYPE_PF: - /* Skip this action, have to add for vxlan */ - break; - case RTE_FLOW_ACTION_TYPE_END: - end_of_list = 1; - break; - default: - DPAA2_PMD_ERR("Invalid action type"); + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + if (attr->priority >= priv->qos_entries) { + DPAA2_PMD_ERR("Prior(%d) is out of range(%d)", + attr->priority, priv->qos_entries); ret = -ENOTSUP; - break; + goto complete_verify; } - j++; + goto complete_verify_group; } -end_flow_set: - if (!ret) { - /* New rules are inserted. */ - if (!curr) { - LIST_INSERT_HEAD(&priv->flows, flow, next); - } else { - while (LIST_NEXT(curr, next)) - curr = LIST_NEXT(curr, next); - LIST_INSERT_AFTER(curr, flow, next); + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW || + group_type == RTE_DPAA2_FS_GROUP_FLOW) { + if (group_id >= priv->num_rx_tc) { + DPAA2_PMD_ERR("Group(%d) is out of range(%d)", + group_id, priv->num_rx_tc); + ret = -ENOTSUP; + goto complete_verify; + } + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW && + (attr->priority + priv->fs_entries * group_id) >= priv->qos_entries) { + DPAA2_PMD_ERR("Prior(%d) + fs entries(%d) * group(%d) is out of range(%d)", + attr->priority, priv->fs_entries, group_id, + priv->qos_entries); + ret = -ENOTSUP; + goto complete_verify; } + } else { + DPAA2_PMD_ERR("Invalid group type(%d)", group_type); + ret = -EINVAL; + goto complete_verify; } - rte_free(dpaa2_pattern); - - return ret; -} - -static inline int -dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, - const struct rte_flow_attr *attr) -{ - int ret = 0; - - if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) { - DPAA2_PMD_ERR("Group/TC(%d) is out of range(%d)", - attr->group, dpni_attr->num_rx_tcs); - ret = -ENOTSUP; - } - if (unlikely(attr->priority >= dpni_attr->fs_entries)) { - DPAA2_PMD_ERR("Priority(%d) within group is out of range(%d)", - attr->priority, dpni_attr->fs_entries); - ret = -ENOTSUP; - } +complete_verify_group: if (unlikely(attr->egress)) { DPAA2_PMD_ERR("Egress flow configuration is not supported"); ret = -ENOTSUP; + goto complete_verify; } if (unlikely(!attr->ingress)) { DPAA2_PMD_ERR("Ingress flag must be configured"); ret = -EINVAL; } + +complete_verify: + if (!ret) { + if (pgroup_type) + *pgroup_type = group_type; + if (pgroup_id) + *pgroup_id = group_id; + } + return ret; } static inline int -dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], +dpaa2_flow_verify_patterns(const struct rte_flow_item pattern[], int sp_support) { unsigned int i, j, is_found = 0; @@ -5109,29 +4736,32 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], } static inline int -dpaa2_dev_verify_actions(const struct rte_flow_action actions[]) +dpaa2_flow_check_actions_support(const struct rte_flow_action actions[], + const enum rte_flow_action_type supported[], uint16_t len) { unsigned int i, j, is_found = 0; - int ret = 0; for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { - for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) { - if (dpaa2_supported_action_type[i] == actions[j].type) { + is_found = 0; + for (i = 0; i < len; i++) { + if (supported[i] == actions[j].type) { is_found = 1; break; } } - if (!is_found) { - ret = -ENOTSUP; - break; - } + if (!is_found) + return false; } for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP && - !actions[j].conf) - ret = -EINVAL; + !actions[j].conf) { + DPAA2_PMD_ERR("No config for actions[%d].type(%d)", + j, actions[j].type); + return false; + } } - return ret; + + return true; } static int @@ -5142,238 +4772,1649 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct dpni_attr dpni_attr; - struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; - uint16_t token = priv->token; + uint16_t supported_len = 0; int ret = 0; + uint32_t group_type; + const enum rte_flow_action_type *supported = NULL; + const char *err_str = NULL; + const void *cause = NULL; + enum rte_flow_error_type err_type = RTE_FLOW_ERROR_TYPE_NONE; - memset(&dpni_attr, 0, sizeof(struct dpni_attr)); - ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr); - if (ret < 0) { - DPAA2_PMD_ERR("Get dpni@%d attribute failed(%d)", - priv->hw_id, ret); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ATTR, - flow_attr, "invalid"); - return ret; + /* Verify input attributes */ + ret = dpaa2_flow_verify_attr(priv, flow_attr, &group_type, NULL); + if (ret) { + err_str = "Invalid attributes are given"; + cause = flow_attr; + err_type = RTE_FLOW_ERROR_TYPE_ATTR; + goto invalid_params; } - /* Verify input attributes */ - ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid attributes are given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ATTR, - flow_attr, "invalid"); - goto not_valid_params; - } - /* Verify input pattern list */ - ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid pattern list is given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ITEM, - pattern, "invalid"); - goto not_valid_params; + if (pattern) { + /* Verify input pattern list */ + ret = dpaa2_flow_verify_patterns(pattern, priv->sp_protocol); + if (ret) { + err_str = "Invalid pattern list is given"; + cause = pattern; + err_type = RTE_FLOW_ERROR_TYPE_ITEM; + goto invalid_params; + } + } + + supported = dpaa2_supported_meter_action_type; + supported_len = RTE_DIM(dpaa2_supported_meter_action_type); + if (dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + DPAA2_PMD_DEBUG("This is meter flow."); + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + err_str = "Meter flow's type can't be QoS flow."; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION; + ret = -EPERM; + goto invalid_params; + } + if (actions[1].type != RTE_FLOW_ACTION_TYPE_END) { + err_str = "Meter flow can't support multi-actions."; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM; + ret = -EPERM; + goto invalid_params; + } + if (pattern) + DPAA2_PMD_WARN("Meter flow ingores flow items!"); + return 0; } + /* Verify input action list */ - ret = dpaa2_dev_verify_actions(actions); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid action list is given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ACTION, - actions, "invalid"); - goto not_valid_params; + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW || + group_type == RTE_DPAA2_FS_GROUP_FLOW) { + supported = dpaa2_supported_fs_action_type; + supported_len = RTE_DIM(dpaa2_supported_fs_action_type); + } else { + supported = dpaa2_supported_qos_action_type; + supported_len = RTE_DIM(dpaa2_supported_qos_action_type); + } + if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + err_str = "Invalid action list is given"; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION; + ret = -ENOTSUP; + goto invalid_params; } -not_valid_params: + +invalid_params: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(error, -ret, err_type, cause, err_str); + return ret; } -static struct rte_flow * -dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) +static int +dpaa2_flow_is_ip_addr_extract(const struct dpkg_extract *extract) { - struct dpaa2_dev_flow *flow = NULL; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - int ret; - uint64_t iova; + enum dpkg_extract_type type = extract->type; + enum net_prot prot = extract->extract.from_hdr.prot; + uint32_t field = extract->extract.from_hdr.field; - dpaa2_flow_control_log = - getenv("DPAA2_FLOW_CONTROL_LOG"); + if (type == DPKG_EXTRACT_FROM_HDR && prot == NET_PROT_IP && + (field == NH_FLD_IP_SRC || field == NH_FLD_IP_DST)) + return true; - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), - RTE_CACHE_LINE_SIZE); - if (!flow) { - DPAA2_PMD_ERR("Failure to allocate memory for flow"); - goto mem_failure; - } + return false; +} - /* Allocate DMA'ble memory to write the qos rules */ - flow->qos_key_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->qos_key_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_key_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for qos key(%p)", - __func__, flow->qos_key_addr); - goto mem_failure; +static int +dpaa2_flow_ip_addr_extract_pos(uint32_t field, + const struct dpaa2_key_profile *profile) +{ + if (field != NH_FLD_IP_SRC && field != NH_FLD_IP_DST) + return -EINVAL; + if (profile->ip_addr_extracts[0].field == field) + return 0; + else if (profile->ip_addr_extracts[1].field == field) + return 1; + else + return -ENXIO; +} + +static int +dpaa2_flow_key_offset_size(struct dpaa2_dev_flow *flow, + struct dpaa2_flow_tbl_profile *tbl_profile, uint8_t idx, + uint8_t *offset, uint8_t *size, + enum dpaa2_flow_dist_type type) +{ + struct dpkg_profile_cfg *dpkg = &tbl_profile->dpkg; + struct dpaa2_key_profile *profile = &tbl_profile->key_profile; + int pos, prev_ip_addr_pos; + uint32_t field; + uint8_t ip_addr_size = 0, ip_addr_offset = 0; + struct dpaa2_generic_flow *_flow; + + _flow = type == DPAA2_FLOW_QOS_TYPE ? flow->qos_flow : flow->fs_flow; + + if (_flow->ip_key == NET_PROT_IPV4) + ip_addr_size = NH_FLD_IPV4_ADDR_SIZE; + else if (_flow->ip_key == NET_PROT_IPV6) + ip_addr_size = NH_FLD_IPV6_ADDR_SIZE; + + field = dpkg->extracts[idx].extract.from_hdr.field; + prev_ip_addr_pos = dpaa2_extract_prev_ip_addr_pos(profile); + if (prev_ip_addr_pos >= 0) { + ip_addr_offset = + profile->key_offset[prev_ip_addr_pos] + + profile->key_size[prev_ip_addr_pos]; } - flow->qos_rule.key_iova = iova; - flow->qos_mask_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->qos_mask_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; + if (dpaa2_flow_is_ip_addr_extract(&dpkg->extracts[idx])) { + pos = dpaa2_flow_ip_addr_extract_pos(field, profile); + if (!ip_addr_size) + return -EINVAL; + *offset = ip_addr_offset + ip_addr_size * pos; + *size = ip_addr_size; + } else { + *offset = profile->key_offset[idx]; + *size = profile->key_size[idx]; } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_mask_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for qos mask(%p)", - __func__, flow->qos_mask_addr); + + return 0; +} + +static int +dpaa2_flow_rule_data_valid(struct dpaa2_dev_flow *flow, + uint8_t key_offset, uint8_t key_size, + enum dpaa2_flow_dist_type type) +{ + uint8_t *mask, i; + int valid = 0; + struct dpaa2_generic_flow *_flow; + + _flow = type == DPAA2_FLOW_QOS_TYPE ? flow->qos_flow : flow->fs_flow; + mask = _flow->mask_addr + key_offset; + + for (i = 0; i < key_size; i++) { + if (mask[i]) { + valid = 1; + break; + } + } + + return valid; +} + +static void +dpaa2_flow_remove_invalid_rule_data(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type type, uint8_t tc_id, + uint8_t key_offset, uint8_t key_size) +{ + struct dpaa2_dev_flow *flow, *next; + struct dpaa2_generic_flow *_flow; + + flow = LIST_FIRST(&priv->flows); + while (flow) { + next = LIST_NEXT(flow, next); + if (type == DPAA2_FLOW_QOS_TYPE) { + _flow = flow->qos_flow; + if (!_flow) + goto skip_update_flow; + } else { + _flow = flow->fs_flow; + if (!_flow) + goto skip_update_flow; + if (_flow->tc_id != tc_id) + goto skip_update_flow; + } + + if (key_offset < _flow->rule_size) { + memmove(_flow->key_addr + key_offset, + _flow->key_addr + key_offset + key_size, + _flow->rule_size - (key_offset + key_size)); + memmove(_flow->mask_addr + key_offset, + _flow->mask_addr + key_offset + key_size, + _flow->rule_size - (key_offset + key_size)); + _flow->rule_size -= key_size; + } + if (_flow->rule_cfg.key_size > _flow->rule_size) { + memset(_flow->key_addr + _flow->rule_size, 0, + _flow->rule_cfg.key_size - _flow->rule_size); + memset(_flow->mask_addr + _flow->rule_size, 0, + _flow->rule_cfg.key_size - _flow->rule_size); + } + +skip_update_flow: + flow = next; + } +} + +static int +dpaa2_flow_remove_invalid_extract(struct rte_eth_dev *dev, + enum dpaa2_flow_dist_type type, uint8_t tc_id) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *flow, *next; + uint8_t i, key_offset, key_size, j, remove_conut = 0; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpkg_profile_cfg *dpkg; + struct dpaa2_key_profile *key_profile; + int valid[DPKG_MAX_NUM_OF_EXTRACTS], update = 0, ret, ipaddr; + enum net_prot prot; + uint32_t field, start, end; + uint32_t ip_src_size, ip_dst_size; + struct dpaa2_generic_flow *_flow; + + if (type == DPAA2_FLOW_QOS_TYPE && + priv->num_rx_tc <= 1) { + /** No QoS table.*/ + return 0; + } + + if (type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + + dpkg = &tbl_profile->dpkg; + key_profile = &tbl_profile->key_profile; + for (i = 0; i < key_profile->num; i++) { + valid[i] = 0; + flow = LIST_FIRST(&priv->flows); + while (flow) { + next = LIST_NEXT(flow, next); + _flow = type == DPAA2_FLOW_QOS_TYPE ? + flow->qos_flow : flow->fs_flow; + if (!_flow) + goto skip_validation; + + if (type == DPAA2_FLOW_FS_TYPE && + _flow->tc_id != tc_id) + goto skip_validation; + + key_offset = 0; + key_size = 0; + + ret = dpaa2_flow_key_offset_size(flow, tbl_profile, i, + &key_offset, &key_size, type); + if (ret) + goto skip_validation; + + if (dpaa2_flow_rule_data_valid(flow, + key_offset, key_size, type)) { + valid[i] = 1; + break; + } +skip_validation: + flow = next; + } + if (!valid[i]) + remove_conut++; + } + + if (remove_conut > 0) { + if (type == DPAA2_FLOW_QOS_TYPE) { + dpaa2_flow_extracts_log(priv, + "Before removing extract(s)", MAX_TCS); + } else { + dpaa2_flow_extracts_log(priv, + "Before removing extract(s)", tc_id); + } + } else { + return 0; + } + + i = key_profile->num - 1; + while (remove_conut) { + if (valid[i]) { + if (i == 0) { + DPAA2_PMD_ERR("Fatal: %d key(s) not removed!", + remove_conut); + return -EINVAL; + } + i--; + continue; + } + key_size = key_profile->key_size[i]; + key_offset = key_profile->key_offset[i]; + + for (j = i + 1; j < key_profile->num; j++) + key_profile->key_offset[j] -= key_size; + + ipaddr = 0; + if (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR) { + prot = dpkg->extracts[i].extract.from_hdr.prot; + field = dpkg->extracts[i].extract.from_hdr.field; + ipaddr = dpaa2_flow_ip_address_extract(prot, field); + } + if (!ipaddr) + update += key_size; + + if ((i + 1) < key_profile->num) { + memmove(&key_profile->key_offset[i], + &key_profile->key_offset[i + 1], + key_profile->num - i - 1); + memmove(&key_profile->key_size[i], + &key_profile->key_size[i + 1], + key_profile->num - i - 1); + memmove(&key_profile->prot_field[i], + &key_profile->prot_field[i + 1], + (key_profile->num - i - 1) * + sizeof(struct key_prot_field)); + + memmove(&dpkg->extracts[i], &dpkg->extracts[i + 1], + (key_profile->num - i - 1) * + sizeof(struct dpkg_extract)); + } + + dpaa2_flow_remove_invalid_rule_data(priv, type, tc_id, + key_offset, key_size); + + key_profile->num--; + dpkg->num_extracts--; + i--; + remove_conut--; + }; + + key_profile->key_max_size -= update; + key_profile->key_max_size -= + (key_profile->ip_addr_extracts[0].max_size + + key_profile->ip_addr_extracts[1].max_size); + + key_profile->l4_sp_present = 0; + key_profile->l4_dp_present = 0; + memset(key_profile->ip_addr_extracts, 0, + sizeof(struct dpaa2_ip_addr_extract) * 2); + + if (key_profile->num >= 2) + start = key_profile->num - 2; + else if (key_profile->num >= 1) + start = key_profile->num - 1; + else + goto skip_ip_addr_extract; + end = key_profile->num; + + j = 0; + for (i = start; i < end; i++) { + if (dpaa2_flow_is_ip_addr_extract(&dpkg->extracts[i])) { + key_profile->ip_addr_extracts[j].field = + dpkg->extracts[i].extract.from_hdr.field; + key_profile->ip_addr_extracts[j].max_size = + sizeof(rte_be32_t); + j++; + } + } + + ip_src_size = sizeof(rte_be32_t); + ip_dst_size = sizeof(rte_be32_t); + flow = LIST_FIRST(&priv->flows); + while (flow) { + next = LIST_NEXT(flow, next); + _flow = type == DPAA2_FLOW_QOS_TYPE ? + flow->qos_flow : flow->fs_flow; + if (!_flow) + goto next_flow; + + if (type == DPAA2_FLOW_FS_TYPE && + _flow->tc_id != tc_id) + goto next_flow; + + if (_flow->ip_key == NET_PROT_IPV6) { + if (_flow->ip_src == NET_PROT_IPV6) + ip_src_size = NH_FLD_IPV6_ADDR_SIZE; + if (_flow->ip_dst == NET_PROT_IPV6) + ip_dst_size = NH_FLD_IPV6_ADDR_SIZE; + } + +next_flow: + flow = next; + } + if (key_profile->ip_addr_extracts[0].field == NH_FLD_IP_SRC) + key_profile->ip_addr_extracts[0].max_size = ip_src_size; + else if (key_profile->ip_addr_extracts[0].field == NH_FLD_IP_DST) + key_profile->ip_addr_extracts[0].max_size = ip_dst_size; + + if (key_profile->ip_addr_extracts[1].field == NH_FLD_IP_SRC) + key_profile->ip_addr_extracts[1].max_size = ip_src_size; + else if (key_profile->ip_addr_extracts[1].field == NH_FLD_IP_DST) + key_profile->ip_addr_extracts[1].max_size = ip_dst_size; + + key_profile->key_max_size += + (key_profile->ip_addr_extracts[0].max_size + + key_profile->ip_addr_extracts[1].max_size); + +skip_ip_addr_extract: + for (i = 0; i < dpkg->num_extracts; i++) { + if ((dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_TCP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_TCP_PORT_SRC) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_UDP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_UDP_PORT_SRC) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_SCTP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_SCTP_PORT_SRC)) { + key_profile->l4_sp_present = 1; + key_profile->l4_sp_extract_idx = i; + key_profile->l4_sp_key_offset = + key_profile->key_offset[i]; + } else if ((dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_TCP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_TCP_PORT_DST) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_UDP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_UDP_PORT_DST) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_SCTP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_SCTP_PORT_DST)) { + key_profile->l4_dp_present = 1; + key_profile->l4_dp_extract_idx = i; + key_profile->l4_dp_key_offset = + key_profile->key_offset[i]; + } + } + + if (type == DPAA2_FLOW_QOS_TYPE) { + dpaa2_flow_extracts_log(priv, + "After removing extract(s)", MAX_TCS); + } else { + dpaa2_flow_extracts_log(priv, + "After removing extract(s)", tc_id); + } + + return update; +} + +static int +dpaa2_flow_remove_generic_entry(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, enum dpaa2_flow_dist_type type) +{ + int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_dev_flow_fs_action *fs_action; + uint8_t tc_id; + + if (type == DPAA2_FLOW_QOS_TYPE) + goto remove_qos_flow; + + fs_action = &flow->flow_action.fs_action; + tc_id = flow->tc_id; + switch (fs_action->action_type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: + case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: + /* Then remove entry from FS table */ + ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token, + flow->tc_id, &flow->rule_cfg); + if (ret) { + DPAA2_PMD_ERR("Remove entry from FS[%d] failed(%d)", + flow->tc_id, ret); + dpaa2_flow_fs_entry_log("Delete failed", flow); + } else { + dpaa2_flow_fs_entry_log("Delete success", flow); + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + tbl_profile->entry_num--; + dpaa2_flow_entry_map_set(tbl_profile->entry_map, + flow->entry_index, 0); + } + break; + case RTE_FLOW_ACTION_TYPE_RSS: + /** Remove QoS entry later.*/ + break; + default: + DPAA2_PMD_ERR("Action(%d) not supported", + fs_action->action_type); + ret = -ENOTSUP; + break; + } + + return ret; + +remove_qos_flow: + if (priv->num_rx_tc > 1) { + /* Remove entry from QoS table first */ + ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, + priv->token, &flow->rule_cfg); + if (ret) { + DPAA2_PMD_ERR("Remove QoS entry failed(%d)", ret); + dpaa2_flow_qos_entry_log("Delete failed", flow); + /** Will not remove FS entry.*/ + } else { + dpaa2_flow_qos_entry_log("Delete success", flow); + tbl_profile = &priv->flow_profile.qos_profile; + tbl_profile->entry_num--; + dpaa2_flow_entry_map_set(tbl_profile->entry_map, + flow->entry_index, 0); + } + } + + return ret; +} + +static int +dpaa2_flow_generic_flow_destroy(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, enum dpaa2_flow_dist_type type) +{ + int ret = 0, update; + uint8_t tc_id = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + dpaa2_dump_extract_map(priv, "Start destroying flow", type, + type == DPAA2_FLOW_FS_TYPE ? flow->tc_id : 0); + + ret = dpaa2_flow_remove_generic_entry(dev, flow, type); + if (ret) + return ret; + + if (type == DPAA2_FLOW_FS_TYPE) + tc_id = flow->tc_id; + + update = dpaa2_flow_remove_invalid_extract(dev, type, tc_id); + if (update > 0) { + if (type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_fs_rss_table_config(priv, + flow->tc_id, false); + if (ret) + DPAA2_PMD_ERR("Re-configure FS table failed(%d)", ret); + } else { + ret = dpaa2_flow_qos_table_config(priv, false); + if (ret) + DPAA2_PMD_ERR("Re-configure QoS table failed(%d)", ret); + } + } + + if (!ret) { + dpaa2_dump_extract_map(priv, "End destroying flow", + type, tc_id); + } + + return ret; +} + +static int +dpaa2_flow_qos_fs_action_set(const struct rte_flow_action actions[], + struct rte_flow_action qos_actions[], + struct rte_flow_action fs_actions[], + uint8_t *qos_action_num, uint8_t *fs_action_num) +{ + uint8_t qos_act_num = 0, fs_act_num = 0; + int end_of_list = 0, i = 0, is_qos_act, is_fs_act; + struct rte_flow_action action_check[2]; + + action_check[1].type = RTE_FLOW_ACTION_TYPE_END; + while (!end_of_list) { + if (actions[i].type == RTE_FLOW_ACTION_TYPE_END) { + if (qos_action_num) + *qos_action_num = qos_act_num; + if (fs_action_num) + *fs_action_num = fs_act_num; + qos_actions[qos_act_num].type = actions[i].type; + fs_actions[fs_act_num].type = actions[i].type; + end_of_list = 1; + continue; + } + action_check[0].type = actions[i].type; + action_check[0].conf = actions[i].conf; + is_qos_act = dpaa2_flow_check_actions_support(action_check, + dpaa2_supported_qos_action_type, + RTE_DIM(dpaa2_supported_qos_action_type)); + is_fs_act = dpaa2_flow_check_actions_support(action_check, + dpaa2_supported_fs_action_type, + RTE_DIM(dpaa2_supported_fs_action_type)); + if (!is_qos_act && !is_fs_act) + return -EINVAL; + if (is_qos_act && is_fs_act) + is_qos_act = false; + if (is_qos_act) { + qos_actions[qos_act_num].type = actions[i].type; + qos_actions[qos_act_num].conf = actions[i].conf; + qos_act_num++; + } + if (is_fs_act) { + fs_actions[fs_act_num].type = actions[i].type; + fs_actions[fs_act_num].conf = actions[i].conf; + fs_act_num++; + } + i++; + } + + return 0; +} + +static struct dpaa2_generic_flow * +dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error, enum dpaa2_flow_dist_type type, + int mix_extract, int is_rss) +{ + struct dpaa2_generic_flow *flow = NULL; + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret, idx = -1; + uint64_t iova, mc_rev; + uint8_t qos_action_num = 0, fs_action_num = 0; + struct rte_flow_action qos_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + struct rte_flow_action fs_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + struct rte_flow_action_jump action_jump; + const struct rte_flow_action_rss *action_rss; + const struct rte_flow_action_queue *action_q; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_queue *dir_rxq = NULL; + + if (type != DPAA2_FLOW_QOS_TYPE && type != DPAA2_FLOW_FS_TYPE) + return NULL; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + mc_rev = dpaa2_dev->bus_info->mc_rev; + + if (actions) { + ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions, + fs_actions, &qos_action_num, &fs_action_num); + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to set qos/fs actions!", ret); + goto creation_error; + } + if (type == DPAA2_FLOW_QOS_TYPE && + dpaa2_flow_action_single_type_check(fs_actions, + RTE_FLOW_ACTION_TYPE_QUEUE)) { + action_q = fs_actions[0].conf; + if (action_q->index >= dev->data->nb_rx_queues) { + DPAA2_PMD_ERR("direct queue index(%d) >= max(%d)", + action_q->index, + dev->data->nb_rx_queues); + ret = -EINVAL; + goto creation_error; + } + if ((mc_rev < DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV || + mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) && + mix_extract) { + /** We don't recommend steering flow by QoS table here + * because this version doesn't support QoS flow HW update + * and QoS table miss flow. + */ + dir_rxq = NULL; + } else { + dir_rxq = dev->data->rx_queues[action_q->index]; + } + } + } + + if (type == DPAA2_FLOW_FS_TYPE && attr) { + if (attr->group >= priv->num_rx_tc) { + DPAA2_PMD_ERR("Flow group(%d) >= max(%d)", + attr->group, priv->num_rx_tc); + return NULL; + } + if (attr->priority >= priv->fs_entries && !is_rss) { + DPAA2_PMD_ERR("FS[%d].entry(%d) >= max(%d)", + attr->group, attr->priority, priv->fs_entries); + return NULL; + } + } + + if (dir_rxq) { + qos_actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + qos_actions[0].conf = &action_jump; + qos_actions[1].type = RTE_FLOW_ACTION_TYPE_END; + /** Ignore attr->group*/ + if ((mix_extract || type == DPAA2_FLOW_FS_TYPE) && + attr->group < priv->num_rx_tc && + attr->group != dir_rxq->tc_index) { + DPAA2_PMD_ERR("Attribute group(%d) conflicts with dest queue's TC(%d)", + attr->group, dir_rxq->tc_index); + return NULL; + } + action_jump.group = dir_rxq->tc_index; + if (attr->group >= priv->num_rx_tc) + idx = attr->priority; + else if (!priv->fs_entries) + idx = action_jump.group * priv->dist_queues + attr->priority; + else + idx = action_jump.group * priv->fs_entries + attr->priority; + } else if (mix_extract && type == DPAA2_FLOW_QOS_TYPE) { + /** Move end action.*/ + rte_memcpy(&qos_actions[qos_action_num + 1], + &qos_actions[qos_action_num], + sizeof(struct rte_flow_action)); + /** Jump to FS[group]*/ + qos_actions[qos_action_num].type = RTE_FLOW_ACTION_TYPE_JUMP; + qos_actions[qos_action_num].conf = &action_jump; + action_jump.group = attr->group; + idx = action_jump.group * priv->fs_entries + attr->priority; + qos_action_num++; + } else if (!mix_extract && type == DPAA2_FLOW_QOS_TYPE) { + if (!qos_action_num) { + DPAA2_PMD_ERR("No QoS flow's action!"); + return NULL; + } + if (!is_rss) { + idx = dpaa2_flow_acquire_entry_idx(priv, attr->priority, + DPAA2_FLOW_QOS_TYPE, attr->group); + } + } else if (type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_verify_fs_action(priv, attr, actions); + if (ret) + return NULL; + if (!is_rss) { + idx = dpaa2_flow_acquire_entry_idx(priv, attr->priority, + DPAA2_FLOW_FS_TYPE, attr->group); + } + } else { + DPAA2_PMD_ERR("Invalid flow type(%d) or extract type(%d)", + type, mix_extract); + return NULL; + } + if (idx < 0 && !is_rss) + return NULL; + if (idx >= 0 && idx < RTE_ETH_DCB_NUM_USER_PRIORITIES && !is_rss && + type == DPAA2_FLOW_QOS_TYPE && priv->dcb_flow[idx]) { + DPAA2_PMD_ERR("QoS flow[%d] added conflicts with dcb flow", idx); + return NULL; + } + + if (!is_rss) { + ret = dpaa2_flow_verify_entry(priv, attr->group, idx, type); + if (ret) + return NULL; + if ((type == DPAA2_FLOW_QOS_TYPE && idx >= priv->qos_entries) || + (type == DPAA2_FLOW_FS_TYPE && idx >= priv->fs_entries)) { + DPAA2_PMD_ERR("%s flow[%d] added more than max entries(%d)", + type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", idx, + type == DPAA2_FLOW_QOS_TYPE ? priv->qos_entries : priv->fs_entries); + return NULL; + } + } + + dpaa2_dump_extract_map(priv, "Start creating flow", + type, attr->group); + + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_generic_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + DPAA2_PMD_ERR("Failure to allocate memory for flow"); goto mem_failure; } - flow->qos_rule.mask_iova = iova; + flow->priv = priv; - /* Allocate DMA'ble memory to write the FS rules */ - flow->fs_key_addr = rte_zmalloc(NULL, + /* Allocate DMA'ble memory to write the qos rules */ + flow->key_addr = rte_zmalloc(NULL, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->fs_key_addr) { + if (!flow->key_addr) { DPAA2_PMD_ERR("Memory allocation failed"); goto mem_failure; } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_key_addr, + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->key_addr, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for fs key(%p)", - __func__, flow->fs_key_addr); + DPAA2_PMD_ERR("%s: No IOMMU map for key(%p)", + __func__, flow->key_addr); goto mem_failure; } - flow->fs_rule.key_iova = iova; + flow->rule_cfg.key_iova = iova; - flow->fs_mask_addr = rte_zmalloc(NULL, + flow->mask_addr = rte_zmalloc(NULL, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->fs_mask_addr) { + if (!flow->mask_addr) { DPAA2_PMD_ERR("Memory allocation failed"); goto mem_failure; } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_mask_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->mask_addr, + DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for fs mask(%p)", - __func__, flow->fs_mask_addr); + DPAA2_PMD_ERR("%s: No IOMMU map for mask(%p)", + __func__, flow->mask_addr); goto mem_failure; } - flow->fs_rule.mask_iova = iova; + flow->rule_cfg.mask_iova = iova; - priv->curr = flow; + flow->ip_key = NET_PROT_NONE; - ret = dpaa2_generic_flow_set(flow, dev, attr, pattern, actions, error); + priv->cur_flow = flow; + if (is_rss) { + action_rss = actions[0].conf; + tbl_profile = &priv->flow_profile.tc_profile[attr->group]; + tbl_profile->tc_cfg.dist_size = action_rss->queue_num; + } + ret = dpaa2_flow_generic_extract_rule_set(flow, + attr, pattern, is_rss, type, false); if (ret < 0) { - if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) + if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) { rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - attr, "unknown"); - DPAA2_PMD_ERR("Create flow failed (%d)", ret); + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + attr, "unknown"); + } + DPAA2_PMD_ERR("Create %s flow failed (%d)", + type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", ret); goto creation_error; } - priv->curr = NULL; - return (struct rte_flow *)flow; + flow->entry_index = idx; + if (type == DPAA2_FLOW_QOS_TYPE) { + ret = dpaa2_flow_qos_action_update(priv, flow, qos_actions, true); + if (ret) + goto creation_error; + if (dir_rxq) { + flow->direct_queue = true; + flow->flow_id = dir_rxq->flow_id; + } + ret = dpaa2_flow_add_qos_rule(priv, flow); + if (ret) + goto creation_error; + } else { + flow->tc_id = attr->group; + ret = dpaa2_flow_fs_action_update(priv, flow, fs_actions); + if (ret) + goto creation_error; + if (!is_rss) { + ret = dpaa2_flow_add_fs_rule(priv, flow); + if (ret) + goto creation_error; + } else { + flow->is_rss = true; + } + } + priv->cur_flow = NULL; + + dpaa2_dump_extract_map(priv, "Complete creating flow", + type, attr->group); + + return flow; mem_failure: rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "memory alloc"); + "memory alloc"); creation_error: if (flow) { - rte_free(flow->qos_key_addr); - rte_free(flow->qos_mask_addr); - rte_free(flow->fs_key_addr); - rte_free(flow->fs_mask_addr); + if (flow->key_addr) + rte_free(flow->key_addr); + if (flow->mask_addr) + rte_free(flow->mask_addr); rte_free(flow); } - priv->curr = NULL; + + return NULL; +} + +static struct rte_flow * +dpaa2_flow_create_meter_flow(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_action meter_action[]) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *flow = NULL; + struct dpaa2_generic_flow *fs_flow = NULL; + int ret; + + if (attr->group >= priv->num_rx_tc) + return NULL; + + if (priv->flow_profile.mtr_flow[attr->group]) + return NULL; + + fs_flow = rte_zmalloc(NULL, sizeof(struct dpaa2_generic_flow), + RTE_CACHE_LINE_SIZE); + if (!fs_flow) { + DPAA2_PMD_ERR("Failure to allocate memory for flow"); + return NULL; + } + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + rte_free(fs_flow); + DPAA2_PMD_ERR("Failure to allocate memory for flow"); + return NULL; + } + fs_flow->tc_id = attr->group; + fs_flow->priv = priv; + flow->fs_flow = fs_flow; + flow->priv = priv; + + ret = dpaa2_flow_fs_action_update(priv, fs_flow, meter_action); + if (ret) { + rte_free(fs_flow); + rte_free(flow); + return NULL; + } + flow->is_meter_flow = true; + priv->flow_profile.mtr_flow[fs_flow->tc_id] = flow; + + return (struct rte_flow *)flow; +} + +static struct rte_flow * +dpaa2_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct dpaa2_dev_flow *flow = NULL, *curr; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret, is_rss = false; + struct dpaa2_generic_flow *qos_flow = NULL; + struct dpaa2_generic_flow *fs_flow = NULL; + uint32_t group_id, group_type; + const struct rte_flow_action_rss *rss_conf; + struct rte_flow_item items[DPKG_MAX_NUM_OF_EXTRACTS + 1]; + int rss_item = false, err_code = 0; + uint8_t spec_buf[1024]; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + struct rte_flow_attr local_attr; + + if (getenv("DPAA2_FLOW_CONTROL_LOG")) + dpaa2_flow_control_log = 1; + + group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr->group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group); + if (group_id >= priv->num_rx_tc && + group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + group_type = RTE_DPAA2_QOS_GROUP_FLOW; + group_id = DPAA2_FLOW_QOS_GROUP_ID; + } + rte_memcpy(&local_attr, attr, sizeof(struct rte_flow_attr)); + local_attr.group = group_id; + + if (actions) { + is_rss = dpaa2_flow_action_single_type_check(actions, + RTE_FLOW_ACTION_TYPE_RSS); + } + if (is_rss && group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + err_str = "RSS doesn't supports QoS table!"; + error_type = RTE_FLOW_ERROR_TYPE_ATTR; + err_code = -EINVAL; + goto flow_failure; + } + if (is_rss && group_type != RTE_DPAA2_FS_GROUP_FLOW) { + DPAA2_PMD_WARN("RSS distribution in TC%d.", group_id); + group_type = RTE_DPAA2_FS_GROUP_FLOW; + } + if (is_rss && !pattern) { + rss_conf = actions[0].conf; + ret = dpaa2_flow_rss_conf_to_item(rss_conf->types, items, + spec_buf, 1024); + if (ret < 0) { + DPAA2_PMD_ERR("TC[%d] converts to RSS items failed(%d)", + group_id, ret); + error_type = RTE_FLOW_ERROR_TYPE_ITEM; + err_code = ret; + err_str = "Failed to converts RSS config type to RSS items!"; + goto flow_failure; + } + rss_item = true; + } + + if (dpaa2_flow_check_actions_support(actions, + dpaa2_supported_meter_action_type, + RTE_DIM(dpaa2_supported_meter_action_type))) { + /** Assume it's meter flow per TC.*/ + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP; + err_code = -EINVAL; + err_str = "Failed to converts RSS config type to RSS items!"; + goto flow_failure; + } + if (actions[1].type != RTE_FLOW_ACTION_TYPE_END) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM; + err_code = -EPERM; + err_str = "Meter flow can't support multi-actions."; + goto flow_failure; + } + flow = (void *)dpaa2_flow_create_meter_flow(dev, &local_attr, actions); + if (flow) + return (struct rte_flow *)flow; + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Failed to create meter flow!"; + goto flow_failure; + } + + DPAA2_PMD_DEBUG("Port %s-%s: group type:%d, group id:%d, total RX TCs:%d", + dev->data->name, __func__, group_type, group_id, priv->num_rx_tc); + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + if (priv->qos_entries > 0) { + qos_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern, + actions, error, DPAA2_FLOW_QOS_TYPE, true, is_rss); + if (!qos_flow) { + err_str = "Failed to create QoS flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } + if (priv->fs_entries > 0 && !(qos_flow && qos_flow->direct_queue)) { + fs_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern, + actions, error, DPAA2_FLOW_FS_TYPE, true, is_rss); + if (!fs_flow) { + if (qos_flow) { + ret = dpaa2_flow_generic_flow_destroy(dev, qos_flow, + DPAA2_FLOW_QOS_TYPE); + if (ret) { + DPAA2_PMD_ERR("%s: QoS flow destroy failed(%d)!", + __func__, ret); + } + } + err_str = "Failed to create FS flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } + } else if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + if (!priv->qos_entries) { + err_str = "No QoS entry available!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + qos_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern, + actions, error, DPAA2_FLOW_QOS_TYPE, false, is_rss); + if (!qos_flow) { + err_str = "QoS flow create failed!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } else if (group_type == RTE_DPAA2_FS_GROUP_FLOW) { + if (!priv->fs_entries && !is_rss) { + err_str = "No FS entry available!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + fs_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, + rss_item ? items : pattern, + actions, error, DPAA2_FLOW_FS_TYPE, false, is_rss); + if (!fs_flow) { + err_str = "FS flow create failed!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } else { + err_str = "Invalid flow attribut parameter!"; + error_type = RTE_FLOW_ERROR_TYPE_ATTR; + err_code = -EINVAL; + goto flow_failure; + } + if (!qos_flow && !fs_flow) { + err_str = "Both QoS flow and FS flow are NULL!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + err_str = "Failure to allocate memory for flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -ENOMEM; + goto flow_failure; + } + flow->qos_flow = qos_flow; + flow->fs_flow = fs_flow; + flow->priv = priv; + if (fs_flow && fs_flow->is_rss) + priv->flow_profile.tc_profile[group_id].rss_flow = flow; + + /* New rules are inserted. */ + curr = LIST_FIRST(&priv->flows); + if (!curr) { + LIST_INSERT_HEAD(&priv->flows, flow, next); + } else { + while (LIST_NEXT(curr, next)) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, flow, next); + } + + return (struct rte_flow *)flow; + +flow_failure: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(error, -err_code, error_type, NULL, err_str); + + if (flow) { + if (flow->qos_flow && flow->qos_flow->key_addr) + rte_free(flow->qos_flow->key_addr); + if (flow->qos_flow && flow->qos_flow->mask_addr) + rte_free(flow->qos_flow->mask_addr); + if (flow->fs_flow && flow->fs_flow->key_addr) + rte_free(flow->fs_flow->key_addr); + if (flow->fs_flow && flow->fs_flow->mask_addr) + rte_free(flow->fs_flow->mask_addr); + if (flow->qos_flow) + rte_free(flow->qos_flow); + if (flow->fs_flow) + rte_free(flow->fs_flow); + rte_free(flow); + } + priv->cur_flow = NULL; return NULL; } static int -dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, - struct rte_flow_error *error) +dpaa2_flow_destroy_meter_flow(struct rte_eth_dev *dev, + struct dpaa2_dev_flow *flow) { - int ret = 0; + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + uint8_t tc_id; + + RTE_ASSERT(!flow->qos_flow && flow->fs_flow); + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + tc_id = flow->fs_flow->tc_id; + RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow); + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = DPNI_POLICER_MODE_NONE; + if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &cfg); + } else { + ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &cfg); + } + if (ret) + return ret; + priv->flow_profile.tc_mtr_profile[tc_id] = NULL; + priv->flow_profile.mtr_flow[tc_id] = NULL; + rte_free(flow->fs_flow); + rte_free(flow); + + return 0; +} + +static int +dpaa2_flow_destroy(struct rte_eth_dev *dev, + struct rte_flow *_flow, struct rte_flow_error *error) +{ + int qos_ret = 0, fs_ret = 0; struct dpaa2_dev_flow *flow; struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + uint8_t tc_id; + + RTE_SET_USED(error); flow = (struct dpaa2_dev_flow *)_flow; + if (flow->is_meter_flow) + return dpaa2_flow_destroy_meter_flow(dev, flow); - switch (flow->action_type) { - case RTE_FLOW_ACTION_TYPE_QUEUE: - case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: - case RTE_FLOW_ACTION_TYPE_PORT_ID: - case RTE_FLOW_ACTION_TYPE_DROP: - if (priv->num_rx_tc > 1) { - /* Remove entry from QoS table first */ - ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, - priv->token, - &flow->qos_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove FS QoS entry failed"); - dpaa2_flow_qos_entry_log("Delete failed", flow, - -1); - abort(); - goto error; + LIST_REMOVE(flow, next); + + if (flow->qos_flow) { + qos_ret = dpaa2_flow_generic_flow_destroy(dev, flow->qos_flow, + DPAA2_FLOW_QOS_TYPE); + if (qos_ret) { + DPAA2_PMD_ERR("%s: destroy QoS flow failed(%d)", + __func__, qos_ret); + } + if (flow->qos_flow->key_addr) + rte_free(flow->qos_flow->key_addr); + if (flow->qos_flow->mask_addr) + rte_free(flow->qos_flow->mask_addr); + rte_free(flow->qos_flow); + flow->qos_flow = NULL; + } + if (flow->fs_flow) { + fs_ret = dpaa2_flow_generic_flow_destroy(dev, flow->fs_flow, + DPAA2_FLOW_FS_TYPE); + if (fs_ret) { + DPAA2_PMD_ERR("%s: destroy FS flow failed(%d)", + __func__, fs_ret); + } + if (flow->fs_flow->key_addr) + rte_free(flow->fs_flow->key_addr); + if (flow->fs_flow->mask_addr) + rte_free(flow->fs_flow->mask_addr); + if (flow->fs_flow->is_rss) { + tc_id = flow->fs_flow->tc_id; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + tbl_profile->rss_flow = NULL; + } + rte_free(flow->fs_flow); + flow->fs_flow = NULL; + } + rte_free(flow); + + if (!qos_ret && !fs_ret) + return 0; + + return qos_ret ? qos_ret : fs_ret; +} + +static int +dpaa2_flow_set_miss_actions(struct rte_eth_dev *dev, + uint32_t group, const struct rte_flow_group_attr *attr, + const struct rte_flow_action actions[], struct rte_flow_error *err) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + enum dpaa2_flow_dist_type flow_type = DPAA2_FLOW_NULL_TYPE; + int end_of_list = 0, i = 0, discard = false, err_code = 0; + const struct rte_flow_action_jump *action_jump = NULL; + const struct rte_flow_action_queue *dest_queue = NULL; + uint32_t group_id, group_type; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + struct dpaa2_queue *miss_rxq = NULL; + uint8_t qos_tc = 0xff; + uint16_t qos_flow = 0xffff; + + RTE_SET_USED(attr); + + group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(group); + if (group_id >= priv->num_rx_tc && + group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + group_type = RTE_DPAA2_QOS_GROUP_FLOW; + group_id = 0; + } + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) + flow_type = DPAA2_FLOW_QOS_TYPE; + else if (group_type == RTE_DPAA2_FS_GROUP_FLOW) + flow_type = DPAA2_FLOW_FS_TYPE; + else if (group >= priv->num_rx_tc) + flow_type = DPAA2_FLOW_QOS_TYPE; + else + flow_type = DPAA2_FLOW_FS_TYPE; + + while (!end_of_list) { + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + dest_queue = actions[i].conf; + if (dest_queue->index >= dev->data->nb_rx_queues) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION_CONF; + err_code = -EINVAL; + err_str = "Queue index overflows"; + goto failure_to_set_miss_actions; } + miss_rxq = priv->rx_vq[dest_queue->index]; + break; + case RTE_FLOW_ACTION_TYPE_JUMP: + action_jump = actions[i].conf; + break; + case RTE_FLOW_ACTION_TYPE_DROP: + discard = true; + break; + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_WARN("Invalid default action type[%d]:(%d)", + i, actions[i].type); + break; } + i++; + } - /* Then remove entry from FS table */ - ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token, - flow->tc_id, &flow->fs_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove entry from FS[%d] failed", - flow->tc_id); - goto error; + if (flow_type == DPAA2_FLOW_QOS_TYPE) { + if (!priv->qos_entries) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "No QoS table available!"; + goto failure_to_set_miss_actions; } - break; - case RTE_FLOW_ACTION_TYPE_RSS: - if (priv->num_rx_tc > 1) { - ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, - priv->token, - &flow->qos_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove RSS QoS entry failed"); - goto error; + if (action_jump && miss_rxq) { + if (action_jump->group != miss_rxq->tc_index) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Jump group conflicts to miss queue's TC"; + goto failure_to_set_miss_actions; } } - break; - default: - DPAA2_PMD_ERR("Action(%d) not supported", flow->action_type); - ret = -ENOTSUP; - break; + if (action_jump) + qos_tc = action_jump->group; + if (miss_rxq) { + qos_tc = miss_rxq->tc_index; + qos_flow = miss_rxq->flow_id; + } + if ((!discard && qos_tc == 0xff) || + (discard && qos_tc != 0xff)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Invalid miss action set for QoS table"; + goto failure_to_set_miss_actions; + } + err_code = dpaa2_flow_qos_table_set_default(priv, discard, qos_tc, qos_flow); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to set miss action for QoS table"; + goto failure_to_set_miss_actions; + } + + return 0; } - LIST_REMOVE(flow, next); - rte_free(flow->qos_key_addr); - rte_free(flow->qos_mask_addr); - rte_free(flow->fs_key_addr); - rte_free(flow->fs_mask_addr); - /* Now free the flow */ - rte_free(flow); + if (!priv->fs_entries) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "No FS table available!"; + goto failure_to_set_miss_actions; + } + if (!discard && !miss_rxq) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Invalid miss action set for FS table"; + goto failure_to_set_miss_actions; + } + if (miss_rxq && miss_rxq->tc_index != group_id) { + error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP; + err_code = -EINVAL; + err_str = "Group conflicts with dest queue's TC ID"; + goto failure_to_set_miss_actions; + } + err_code = dpaa2_flow_fs_table_set_default(priv, group_id, discard, + dest_queue ? dest_queue->index : 0); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to set miss action for FS table"; + } -error: - if (ret) - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, "unknown"); - return ret; +failure_to_set_miss_actions: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(err, -err_code, error_type, NULL, err_str); + + return err_code; +} + +static int +dpaa2_flow_actions_update(struct rte_eth_dev *dev, + struct rte_flow *_flow, + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *flow; + struct dpaa2_flow_tbl_profile *tbl_profile = NULL; + int ret = 0, is_rss = false, hw_update = false, err_code = 0, qos_direct; + struct dpaa2_dev_flow_fs_action *fs_action; + uint8_t qos_action_num = 0, fs_action_num = 0, tc_id; + struct rte_flow_action qos_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + struct rte_flow_action fs_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + const struct rte_flow_action_rss *rss_conf; + struct rte_flow_action_jump jump_conf; + struct rte_flow_item items[DPKG_MAX_NUM_OF_EXTRACTS + 1]; + uint8_t spec_buf[1024]; + struct rte_flow_attr attr; + const enum rte_flow_action_type *supported = NULL; + uint16_t supported_len = 0; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + const struct rte_flow_action_queue *action_q; + struct dpaa2_queue *rxq = NULL; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + /* check for the valid flow */ + flow = (void *)_flow; + if (flow->is_meter_flow) { + RTE_ASSERT(flow->fs_flow); + tc_id = flow->fs_flow->tc_id; + RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow); + supported = dpaa2_supported_meter_action_type; + supported_len = RTE_DIM(dpaa2_supported_meter_action_type); + if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to verify meter action!"; + err_code = -ENOTSUP; + goto quit; + } + ret = dpaa2_flow_fs_action_update(priv, flow->fs_flow, actions); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update meter action!"; + err_code = ret; + } + goto quit; + } + LIST_FOREACH(flow, &priv->flows, next) { + if ((struct rte_flow *)flow == _flow) + goto action_update; + } + DPAA2_PMD_ERR("%s: Flow(%p) is not in %s's flow list", + __func__, flow, dev->data->name); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Invalid flow for action update!"; + err_code = -EINVAL; + + goto quit; + +action_update: + if (flow->fs_flow) { + supported = dpaa2_supported_fs_action_type; + supported_len = RTE_DIM(dpaa2_supported_fs_action_type); + } else { + supported = dpaa2_supported_qos_action_type; + supported_len = RTE_DIM(dpaa2_supported_qos_action_type); + } + if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to verify QoS/FS action!"; + err_code = -ENOTSUP; + goto quit; + } + ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions, fs_actions, + &qos_action_num, &fs_action_num); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to set QoS/FS action!"; + err_code = ret; + goto quit; + } + flow = (struct dpaa2_dev_flow *)_flow; + qos_direct = false; + if (flow->qos_flow && flow->qos_flow->direct_queue) + qos_direct = true; + if (flow->fs_flow && flow->qos_flow && qos_action_num > 0) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM; + err_str = "One-level flow can't update QoS action!"; + err_code = -ENOTSUP; + goto quit; + } + if ((!flow->fs_flow && fs_action_num > 0 && !qos_direct) || + (!flow->qos_flow && qos_action_num > 0)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Flow type and flow action don't match!"; + err_code = -EINVAL; + goto quit; + } + if (fs_action_num > 0 && + dpaa2_flow_action_single_type_check(fs_actions, + RTE_FLOW_ACTION_TYPE_QUEUE)) { + action_q = fs_actions[0].conf; + if (action_q->index >= dev->data->nb_rx_queues) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Queue index is too large!"; + err_code = -EINVAL; + goto quit; + } + rxq = dev->data->rx_queues[action_q->index]; + if (flow->fs_flow && flow->fs_flow->tc_id != rxq->tc_index) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Update queue is not in this TC!"; + err_code = -EINVAL; + goto quit; + } + } + + if (!flow->fs_flow) + goto qos_action_update; + fs_action = &flow->fs_flow->flow_action.fs_action; + if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_RSS) { + is_rss = true; + tc_id = flow->fs_flow->tc_id; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + if (tbl_profile->rss_flow != flow) { + DPAA2_PMD_ERR("%s: RSS flow(%p) != TC[%d]'s rss flow(%p)", + __func__, flow, flow->fs_flow->tc_id, tbl_profile->rss_flow); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "The flow to update is not specified TC's RSS flow!"; + err_code = -EINVAL; + goto quit; + } + } + if (fs_action_num > 0 && + fs_actions[0].type != RTE_FLOW_ACTION_TYPE_PORT_ID && + fs_actions[0].type != RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT && + dpaa2_dev->bus_info->mc_rev >= DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV) { + /** Action HW update doesn't support redirecting frames to other DPNIs.*/ + hw_update = true; + goto skip_remove_fs_entry; + } + + if (!is_rss) { + ret = dpaa2_flow_remove_generic_entry(dev, flow->fs_flow, + DPAA2_FLOW_FS_TYPE); + if (ret) { + DPAA2_PMD_ERR("%s: remove flow fs entry failed(%d)", + __func__, ret); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to remove flow in flow action update!"; + err_code = ret; + + goto quit; + } + } + +skip_remove_fs_entry: + if (is_rss) { + rss_conf = fs_actions[0].conf; + ret = dpaa2_flow_rss_conf_to_item(rss_conf->types, items, + spec_buf, 1024); + if (ret < 0) { + DPAA2_PMD_ERR("TC[%d] converts to RSS items failed(%d)", + flow->fs_flow->tc_id, ret); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to gen rss items in flow action update!"; + err_code = ret; + goto quit; + } else if (!ret) { + DPAA2_PMD_ERR("No item is generated by rss type(0x%" PRIx64 ")", + rss_conf->types); + error_type = RTE_FLOW_ERROR_TYPE_ITEM; + err_str = "No item is generated by rss type!"; + err_code = -ENOTSUP; + goto quit; + } + memset(&attr, 0, sizeof(attr)); + attr.group = flow->fs_flow->tc_id; + attr.ingress = 1; + tbl_profile->tc_cfg.dist_size = rss_conf->queue_num; + memset(&flow->fs_flow->rule_cfg, 0, sizeof(struct dpni_rule_cfg)); + memset(flow->fs_flow->key_addr, 0, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + memset(flow->fs_flow->mask_addr, 0, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + flow->fs_flow->rule_size = 0; + flow->fs_flow->ip_key = NET_PROT_NONE; + flow->fs_flow->ip_src = NET_PROT_NONE; + flow->fs_flow->ip_dst = NET_PROT_NONE; + ret = dpaa2_flow_generic_extract_rule_set(flow->fs_flow, &attr, + items, true, DPAA2_FLOW_FS_TYPE, true); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "RSS action update failed!"; + err_code = ret; + goto quit; + } + } else { + ret = dpaa2_flow_fs_action_update(priv, flow->fs_flow, fs_actions); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "FS action update failed!"; + err_code = ret; + goto quit; + } + if (hw_update) + ret = dpaa2_flow_update_fs_rule_action(priv, flow->fs_flow); + else + ret = dpaa2_flow_add_fs_rule(priv, flow->fs_flow); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "FS rule action update failed!"; + err_code = ret; + goto quit; + } + } +qos_action_update: + if (!flow->qos_flow) + goto quit; + + if (rxq) { + jump_conf.group = rxq->tc_index; + qos_actions[qos_action_num].type = RTE_FLOW_ACTION_TYPE_JUMP; + qos_actions[qos_action_num].conf = &jump_conf; + qos_actions[qos_action_num + 1].type = RTE_FLOW_ACTION_TYPE_END; + } + + hw_update = false; + if (dpaa2_dev->bus_info->mc_rev >= DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV) { + /** Action HW update doesn't support redirecting frames to other DPNIs.*/ + hw_update = true; + goto skip_remove_qos_entry; + } + + ret = dpaa2_flow_remove_generic_entry(dev, flow->qos_flow, + DPAA2_FLOW_QOS_TYPE); + if (ret) { + DPAA2_PMD_ERR("%s: remove flow qos entry failed(%d)", + __func__, ret); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to remove QoS entry in action update!"; + err_code = ret; + + goto quit; + } + +skip_remove_qos_entry: + ret = dpaa2_flow_qos_action_update(priv, flow->qos_flow, qos_actions, + false); + if (ret) { + DPAA2_PMD_ERR("%s: QoS action update failed(%d)", + __func__, ret); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to QoS action update!"; + err_code = ret; + + goto quit; + } + if (rxq) { + flow->qos_flow->direct_queue = true; + flow->qos_flow->flow_id = rxq->flow_id; + } + if (hw_update) + ret = dpaa2_flow_update_qos_rule_action(priv, flow->qos_flow); + else + ret = dpaa2_flow_add_qos_rule(priv, flow->qos_flow); + if (ret) { + DPAA2_PMD_ERR("%s: %s qos flow entry failed(%d)", + __func__, hw_update ? "update" : "add", ret); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update QoS entry action to HW!"; + err_code = ret; + } + +quit: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + return rte_flow_error_set(error, -err_code, error_type, NULL, err_str); } /** @@ -5390,24 +6431,113 @@ dpaa2_flow_flush(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_dev_flow *flow = LIST_FIRST(&priv->flows); + int ret = 0; while (flow) { struct dpaa2_dev_flow *next = LIST_NEXT(flow, next); - dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error); + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error); + if (ret) { + DPAA2_PMD_ERR("%s: Remove flow failed(%d)", + __func__, ret); + } + flow = next; } - return 0; + + return ret; } static int -dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, - struct rte_flow *_flow __rte_unused, - const struct rte_flow_action *actions __rte_unused, - void *data __rte_unused, - struct rte_flow_error *error __rte_unused) +dpaa2_flow_query(struct rte_eth_dev *dev, + struct rte_flow *_flow, const struct rte_flow_action *actions, + void *data, struct rte_flow_error *error) { - return 0; + struct dpaa2_dev_flow *flow; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + uint16_t num = 0, num_rsp, i, tc_id = 0; + int ret = 0, found = false; + size_t size, iova; + struct dpni_dump_table_rsp *rsp = NULL; + + RTE_SET_USED(actions); + RTE_SET_USED(data); + RTE_SET_USED(error); + + flow = LIST_FIRST(&priv->flows); + while (flow) { + num++; + if (flow == (struct dpaa2_dev_flow *)_flow) + found = true; + flow = LIST_NEXT(flow, next); + } + if (!num || !found) + return -ENXIO; + num = num * 2;/** Max: FS entry + QoS entry.*/ + flow = (void *)_flow; + size = sizeof(struct dpni_dump_table_header) + + num * sizeof(struct dpni_dump_table_entry); + rsp = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + if (!rsp) + return -ENOMEM; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(rsp, size); + if (iova == RTE_BAD_IOVA) { + DPAA2_PMD_ERR("%s: No IOMMU map for dump table result!", + __func__); + ret = -EIO; + goto quit; + } + + if (priv->num_rx_tc <= 1) + goto dump_fs; + + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_QOS_TABLE, 0/**Any*/, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's QoS table failed(%d)", + dev->data->name, ret); + goto quit; + } + + if (!flow->qos_flow) + goto dump_fs; + + for (i = 0; i < num_rsp; i++) { + if (!memcmp(rsp->entry[i].key, flow->qos_flow->key_addr, + flow->qos_flow->rule_size) && + !memcmp(rsp->entry[i].mask, + flow->qos_flow->mask_addr, flow->qos_flow->rule_size)) + break; + } + +dump_fs: + if (!flow->fs_flow) + goto quit; + + tc_id = flow->fs_flow->tc_id; + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_FS_TABLE, tc_id, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's FS%d table failed(%d)", + dev->data->name, tc_id, ret); + goto quit; + } + for (i = 0; i < num_rsp; i++) { + if (!memcmp(rsp->entry[i].key, flow->fs_flow->key_addr, + flow->fs_flow->rule_size) && + !memcmp(rsp->entry[i].mask, + flow->fs_flow->mask_addr, flow->fs_flow->rule_size)) { + break; + } + } + +quit: + if (rsp) + rte_free(rsp); + + return ret; } /** @@ -5420,19 +6550,45 @@ dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, * Pointer to private structure. */ void -dpaa2_flow_clean(struct rte_eth_dev *dev) +dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id) { - struct dpaa2_dev_flow *flow; + struct dpaa2_dev_flow *flow, *next_flow; struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret; - while ((flow = LIST_FIRST(&priv->flows))) - dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + flow = LIST_FIRST(&priv->flows); + if (tc_id >= MAX_TCS) + goto clean_all; + while (flow) { + next_flow = LIST_NEXT(flow, next); + if (flow->fs_flow && flow->fs_flow->tc_id == tc_id) { + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + if (ret) { + DPAA2_PMD_ERR("%s: Remove flow failed(%d)", + __func__, ret); + } + } + flow = next_flow; + } + return; + +clean_all: + while (flow) { + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + if (ret) { + DPAA2_PMD_ERR("%s: Remove flow failed(%d)", + __func__, ret); + } + flow = LIST_FIRST(&priv->flows); + } } const struct rte_flow_ops dpaa2_flow_ops = { .create = dpaa2_flow_create, .validate = dpaa2_flow_validate, .destroy = dpaa2_flow_destroy, + .group_set_miss_actions = dpaa2_flow_set_miss_actions, + .actions_update = dpaa2_flow_actions_update, .flush = dpaa2_flow_flush, .query = dpaa2_flow_query, }; diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4f774f7c82..3f8bee9146 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2021 NXP +# Copyright 2018-2026 NXP if not is_linux build = false @@ -8,7 +8,6 @@ endif deps += ['mempool_dpaa2'] sources = files( - 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', 'dpaa2_meter.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 38/45] net/dpaa2: support Rx mempool per traffic class 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (36 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 37/45] net/dpaa2: rework flow engine Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 39/45] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta ` (12 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Support configuring RX mempool per TC. This patch isolates mempools by traffic class to avoid individual TC's performance being impacted by lack of memory. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 115 ++++++++++++++++++++++++++++++- drivers/net/dpaa2/dpaa2_ethdev.h | 2 +- 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index a7c9bb678e..a33d6c5db6 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -565,6 +565,97 @@ dpaa2_update_flow_rss_dist(struct rte_eth_dev *eth_dev, return ret; } +static int +dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, + struct fsl_mc_io *dpni, void *blist, uint8_t tc_id) +{ + /* Function to attach a DPNI with a buffer pool list. Buffer pool list + * handle is passed in blist. + */ + int32_t retcode; + struct dpni_pools_cfg *bpool_cfg = &priv->pools_cfg; + struct dpaa2_bp_list *bp_list = blist; + struct dpni_buffer_layout layout; + int tot_size, out_min_hdr_room, in_min_hdr_room; + uint8_t bp_idx; + struct rte_mempool *mp = bp_list->mp; + + if (priv->flow_profile.mempool[tc_id] != mp) { + if (!priv->flow_profile.mempool[tc_id]) { + bp_idx = bpool_cfg->num_dpbp; + bpool_cfg->num_dpbp++; + priv->flow_profile.bp_idx[tc_id] = bp_idx; + } else { + bp_idx = priv->flow_profile.bp_idx[tc_id]; + } + priv->flow_profile.mempool[tc_id] = mp; + } else { + bp_idx = priv->flow_profile.bp_idx[tc_id]; + } + + /* ... rx buffer layout . + * Check alignment for buffer layouts first + */ + + /* ... rx buffer layout ... */ + if (priv->tx_conf_type == DPAA2_TX_DYNAMIC_CONF) { + /** Additional headroom layout for IPSec with TX configure + * dynamic enabled. + */ + in_min_hdr_room = DPAA2_RX_MIN_FD_OFFSET + + DPAA2_SEC_SIMPLE_FD_IB_MIN; + out_min_hdr_room = DPAA2_DYN_TX_MIN_FD_OFFSET + + DPAA2_SEC_SIMPLE_FD_OB_MIN; + tot_size = RTE_MAX(in_min_hdr_room, out_min_hdr_room); + if (tot_size < RTE_PKTMBUF_HEADROOM) + tot_size = RTE_PKTMBUF_HEADROOM; + } else { + tot_size = RTE_PKTMBUF_HEADROOM; + } + tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN); + + memset(&layout, 0, sizeof(struct dpni_buffer_layout)); + layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | + DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | + DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | + DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | + DPNI_BUF_LAYOUT_OPT_TIMESTAMP | + DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; + + layout.pass_timestamp = true; + layout.pass_frame_status = 1; + layout.private_data_size = DPAA2_FD_PTA_SIZE; + layout.pass_parser_result = 1; + layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN; + layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - + DPAA2_MBUF_HW_ANNOTATION; + retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token, + DPNI_QUEUE_RX, &layout); + if (retcode) { + DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)", + retcode); + return retcode; + } + + /*Attach buffer pool to the network interface as described by the user*/ + bpool_cfg->pools[bp_idx].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; + bpool_cfg->pools[bp_idx].backup_pool = 0; + bpool_cfg->pools[bp_idx].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size, + DPAA2_PACKET_LAYOUT_ALIGN); + bpool_cfg->pools[bp_idx].priority_mask = tc_id; + + retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, bpool_cfg); + if (retcode) { + DPAA2_PMD_ERR("Error(%d) configuring pools[%d](id=%d) on %s.", + retcode, bp_idx, bpool_cfg->pools[bp_idx].dpbp_id, + priv->eth_dev->data->name); + return retcode; + } + + priv->bp_list = bp_list; + return 0; +} + static int dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { @@ -1340,7 +1431,8 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, struct dpni_taildrop taildrop; uint8_t qopt = 0; uint16_t flow_id; - int ret; + uint32_t bpid; + int ret, ops_idx; PMD_INIT_FUNC_TRACE(); @@ -1365,6 +1457,27 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } + + ops_idx = rte_dpaa2_mpool_get_ops_idx(); + if (ops_idx != mb_pool->ops_index) { + DPAA2_PMD_ERR("MP(%s)'s ops index(%d) != %d", + mb_pool->name, mb_pool->ops_index, ops_idx); + return -EINVAL; + } + + if (!priv->bp_list || priv->bp_list->mp != mb_pool) { + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + ret = rte_dpaa2_bpid_info_init(mb_pool); + if (ret) + return ret; + } + bpid = mempool_to_bpid(mb_pool); + ret = dpaa2_attach_bp_list(priv, dpni, + rte_dpaa2_bpid_info[bpid].bp_list, + dpaa2_q->tc_index); + if (ret) + return ret; + } cfg = rte_zmalloc(NULL, sizeof(struct dpni_queue), 0); if (!cfg) return -ENOMEM; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 5659abcd51..7d93b75be3 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -404,7 +404,7 @@ struct dpaa2_dev_priv { /** RXQs in same TC share same cgid.*/ uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; - + struct dpni_pools_cfg pools_cfg; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. * Zero means "use default" (= nb_rx_queues clamped to dist_queues). -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 39/45] drivers: consume dpaa2 DQRR entries in batches 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (37 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 38/45] net/dpaa2: support Rx mempool per traffic class Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 40/45] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta ` (11 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Each DQRR entry consumed by the software portal costs a write to the cache-invalidate DCAP register. The DCAP register also supports a vector mode where a bitmap of DQRR indices is consumed with a single write, so accumulate the indices and flush the vector once half the ring is pending. A smaller threshold gives little benefit, and a threshold close to the ring size starves WRIOP of DQRR space. Because entries are now released in batches, a caller that stops polling a portal must flush the pending vector explicitly. Pass a NULL dequeue result to qbman_swp_dqrr_consume() to do that when the eventdev dequeue finds the portal dry, when the net PMD finishes draining a portal, and when a portal is released back to the bus. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 4 ++ .../fslmc/qbman/include/fsl_qbman_portal.h | 5 +- drivers/bus/fslmc/qbman/qbman_portal.c | 63 +++++++++++++++++-- drivers/bus/fslmc/qbman/qbman_portal.h | 11 +++- drivers/event/dpaa2/dpaa2_eventdev.c | 4 ++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 + 6 files changed, 81 insertions(+), 8 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 20d1bb2a66..cfd9548fb0 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -305,6 +305,10 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) { if (dpio_dev) { + /* consume indices may still be pending in the portal's DQRR + * consume vector; flush them before the portal is released. + */ + qbman_swp_dqrr_consume(dpio_dev->sw_portal, NULL); /* rx-queue interrupts (net PMD) can arm a portal without the * event driver; tear it down unconditionally. Safe when never * armed: intr_deinit returns early if intr is not enabled. diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index b9e7789766..73e57bcdc1 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -451,7 +451,10 @@ void qbman_swp_prefetch_dqrr_next(struct qbman_swp *s); * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from * qbman_swp_dqrr_next(). * @s: the software portal object. - * @dq: the DQRR entry to be consumed. + * @dq: the DQRR entry to be consumed, NULL to consume the entries accumulated + * so far. Entries are accumulated and consumed in batches, so a caller which + * stops polling the portal must call this with a NULL dq to release the + * entries it has already processed. */ __rte_internal void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq); diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index c93bec5dd3..c95c62baa7 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020,2023-2024 NXP + * Copyright 2018-2020,2023-2024,2026 NXP * */ @@ -9,13 +9,20 @@ #include "qbman_portal.h" #include <eal_export.h> +#include <rte_bitops.h> /* QBMan portal management command codes */ #define QBMAN_MC_ACQUIRE 0x30 #define QBMAN_WQCHAN_CONFIGURE 0x46 /* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ -#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6) +#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) + +/* DCAP consume-index-vector mode: the vector of DQRR indices to consume starts + * at bit 16 of DCAP and bit 8 selects vector mode over single-index mode. + */ +#define DQRR_DCAP_CI_VEC_OFFSET 16 +#define DQRR_DCAP_CI_VEC_SELECT 0x100 /* QBMan FQ management command codes */ #define QBMAN_FQ_SCHEDULE 0x48 @@ -284,6 +291,13 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) p->dqrr.dqrr_size = 8; p->dqrr.reset_bug = 0; } + /* Consume DQRR entries in vector mode by default and flush the vector + * once half the ring is pending. A smaller threshold gives little + * benefit; a threshold close to the ring size starves WRIOP of DQRR + * space and slows its enqueues down. + */ + p->dqrr.ci_vec_en = true; + p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { @@ -2225,13 +2239,47 @@ const struct qbman_result *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s) return p; } -/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ +/* Write the pending consume vector to DCAP if it holds at least "threshold" + * indices, consuming all of them with a single register access. + */ +static inline void +qbman_swp_dqrr_vec_flush(struct qbman_swp *s, uint8_t threshold) +{ + if (s->dqrr.ci_count < threshold) + return; + + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + s->dqrr.ci_vector | DQRR_DCAP_CI_VEC_SELECT); + s->dqrr.ci_vector = 0; + s->dqrr.ci_count = 0; +} + +/* Add a DQRR index to the pending consume vector, flushing it once the + * configured threshold is reached. + */ +static inline void +qbman_swp_dqrr_vec_consume(struct qbman_swp *s, uint8_t idx) +{ + s->dqrr.ci_vector |= RTE_BIT32(idx + DQRR_DCAP_CI_VEC_OFFSET); + s->dqrr.ci_count++; + qbman_swp_dqrr_vec_flush(s, s->dqrr.ci_flush_th); +} + +/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). + * A NULL dq flushes any indices still pending in the consume vector, which + * the caller must do before it stops polling the portal. + */ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_consume) void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq) { - qbman_cinh_write(&s->sys, - QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); + if (unlikely(dq == NULL)) + qbman_swp_dqrr_vec_flush(s, 1); + else if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, QBMAN_IDX_FROM_DQRR(dq)); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + QBMAN_IDX_FROM_DQRR(dq)); } /* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ @@ -2239,7 +2287,10 @@ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_idx_consume) void qbman_swp_dqrr_idx_consume(struct qbman_swp *s, uint8_t dqrr_index) { - qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); + if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, dqrr_index); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); } /*********************************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.h b/drivers/bus/fslmc/qbman/qbman_portal.h index 1cf7918309..db74db5fe1 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.h +++ b/drivers/bus/fslmc/qbman/qbman_portal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020 NXP + * Copyright 2018-2020, 2026 NXP * */ @@ -93,6 +93,15 @@ struct qbman_swp { uint32_t valid_bit; uint8_t dqrr_size; int reset_bug; + /* Consume index vector: instead of writing DCAP once per + * consumed entry, the indices are accumulated in ci_vector + * and written with a single DCAP access once ci_count + * reaches ci_flush_th. + */ + bool ci_vec_en; + uint8_t ci_count; + uint8_t ci_flush_th; + uint32_t ci_vector; } dqrr; struct { uint32_t pi; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 95d9154b11..5d32bd9fd6 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -320,6 +320,10 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], do { dq = qbman_swp_dqrr_next(swp); if (!dq) { + /* portal is dry: consume whatever is still pending in + * the DQRR consume vector before leaving it idle. + */ + qbman_swp_dqrr_consume(swp, NULL); if (!num_pkts && timeout_ticks) { dpaa2_eventdev_dequeue_wait(timeout_ticks); timeout_ticks = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index a33d6c5db6..34f1e00b12 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3533,6 +3533,8 @@ dpaa2_napi_drain_portal(struct dpaa2_dpio_dev *dpio) while ((dq = qbman_swp_dqrr_next(dpio->sw_portal))) qbman_swp_dqrr_consume(dpio->sw_portal, dq); + /* flush the indices still pending in the DQRR consume vector */ + qbman_swp_dqrr_consume(dpio->sw_portal, NULL); qbman_swp_interrupt_clear_status(dpio->sw_portal, 0xffffffff); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 40/45] drivers: resolve dpaa2 endpoint in the net driver 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (38 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 39/45] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 41/45] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta ` (10 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPRC object driver walked every device on the bus and, for each DPNI, issued dprc_get_connection() to find the object it is wired to. Two things are wrong with that. The bus keeps the result in struct rte_dpaa2_device even though only the net driver consumes it, and a failure to resolve one DPNI's endpoint aborted the creation of the whole container. The endpoint name was also formatted from endpoint2 outside the DPNI branch, so non-DPNI devices got a name built from uninitialised or stale data. Move the lookup to dpaa2_dev_init(), which already knows it is dealing with a DPNI and can fail the probe of that one port. This also fills in priv->ep_dev_type, priv->ep_object_id and priv->ep_name, which the net driver reads for MAC-level operations, recycle/loopback configuration and rte_pmd_dpaa2_ep_name(), but which nothing assigned. dpsw endpoints are now recognised, and dpdmux/dpsw names carry the interface index because those endpoints are per-interface. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 3 -- drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 45 +++--------------- drivers/net/dpaa2/dpaa2_ethdev.c | 58 +++++++++++++++++++++++- drivers/net/dpaa2/dpaa2_recycle.c | 15 +++--- 4 files changed, 70 insertions(+), 51 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index b4a5a86318..0d431fdd19 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -104,10 +104,7 @@ struct rte_dpaa2_device { struct rte_device device; /**< Inherit core device */ enum rte_dpaa2_dev_type dev_type; /**< Device Type */ uint16_t object_id; /**< DPAA2 Object ID */ - enum rte_dpaa2_dev_type ep_dev_type; /**< Endpoint Device Type */ struct dpaa2_dprc_dev *container; - uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */ - char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ struct rte_dma_dev *dmadev; /**< DMA device */ diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c index 868ed646af..6441297ecf 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c @@ -27,7 +27,6 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, struct rte_dpaa2_device *obj) { struct dpaa2_dprc_dev *dprc_node; - struct dprc_endpoint endpoint1, endpoint2; struct rte_dpaa2_device *dev; int ret, dprc_id = obj->object_id; @@ -49,45 +48,13 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, return ret; } - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - /** DPRC is always created before it's children are created.*/ + /* DPRC is always created before its children are created, so every + * device scanned so far belongs to this container. Endpoint lookup is + * left to the object drivers, which know how many interfaces their + * object has and can report a failure to their own caller. + */ + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) dev->container = dprc_node; - if (dev->dev_type == DPAA2_ETH) { - int link_state; - - memset(&endpoint1, 0, sizeof(struct dprc_endpoint)); - memset(&endpoint2, 0, sizeof(struct dprc_endpoint)); - strcpy(endpoint1.type, "dpni"); - endpoint1.id = dev->object_id; - ret = dprc_get_connection(&dprc_node->dprc, - CMD_PRI_LOW, - dprc_node->token, - &endpoint1, &endpoint2, - &link_state); - if (ret) { - DPAA2_BUS_ERR("dpni.%d connection failed!", - dev->object_id); - dprc_close(&dprc_node->dprc, CMD_PRI_LOW, - dprc_node->token); - rte_free(dprc_node); - return ret; - } - - if (!strcmp(endpoint2.type, "dpmac")) - dev->ep_dev_type = DPAA2_MAC; - else if (!strcmp(endpoint2.type, "dpni")) - dev->ep_dev_type = DPAA2_ETH; - else if (!strcmp(endpoint2.type, "dpdmux")) - dev->ep_dev_type = DPAA2_MUX; - else - dev->ep_dev_type = DPAA2_UNKNOWN; - - dev->ep_object_id = endpoint2.id; - } else { - dev->ep_dev_type = DPAA2_UNKNOWN; - } - sprintf(dev->ep_name, "%s.%d", endpoint2.type, endpoint2.id); - } TAILQ_INSERT_TAIL(&dprc_dev_list, dprc_node, next); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 34f1e00b12..7cd38ddce6 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3927,6 +3927,55 @@ dpaa2_get_devargs(struct rte_devargs *devargs, const char *key) return 1; } +/* Resolve the object this DPNI is wired to inside its DPRC container. The + * endpoint decides whether MAC-level operations (link, promisc, flow control) + * are available, and it is reported to the application by + * rte_pmd_dpaa2_ep_name(). + */ +static int +dpaa2_dev_ep_init(struct rte_dpaa2_device *dpaa2_dev, + struct dpaa2_dev_priv *priv) +{ + struct dpaa2_dprc_dev *dprc_node = dpaa2_dev->container; + struct dprc_endpoint endpoint1, endpoint2; + int link_state, ret; + + memset(&endpoint1, 0, sizeof(endpoint1)); + memset(&endpoint2, 0, sizeof(endpoint2)); + strlcpy(endpoint1.type, "dpni", sizeof(endpoint1.type)); + endpoint1.id = dpaa2_dev->object_id; + ret = dprc_get_connection(&dprc_node->dprc, CMD_PRI_LOW, + dprc_node->token, &endpoint1, &endpoint2, + &link_state); + if (ret != 0) + return ret; + + if (strcmp(endpoint2.type, "dpmac") == 0) + priv->ep_dev_type = DPAA2_MAC; + else if (strcmp(endpoint2.type, "dpni") == 0) + priv->ep_dev_type = DPAA2_ETH; + else if (strcmp(endpoint2.type, "dpdmux") == 0) + priv->ep_dev_type = DPAA2_MUX; + else if (strcmp(endpoint2.type, "dpsw") == 0) + priv->ep_dev_type = DPAA2_SW; + else + priv->ep_dev_type = DPAA2_UNKNOWN; + + priv->ep_object_id = endpoint2.id; + + /* dpdmux and dpsw endpoints are per-interface, so the interface index + * is part of the name. + */ + if (priv->ep_dev_type == DPAA2_MUX || priv->ep_dev_type == DPAA2_SW) + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d.%d", + endpoint2.type, endpoint2.id, endpoint2.if_id); + else + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d", + endpoint2.type, endpoint2.id); + + return 0; +} + static int dpaa2_dev_init(struct rte_eth_dev *eth_dev) { @@ -4020,6 +4069,13 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + ret = dpaa2_dev_ep_init(dpaa2_dev, priv); + if (ret) { + DPAA2_PMD_ERR("Failure in get dpni@%d endpoint, err code %d", + hw_id, ret); + goto init_err; + } + ret = dpni_get_api_version(dpni_dev, CMD_PRI_LOW, &priv->dpni_ver_major, &priv->dpni_ver_minor); if (ret) { @@ -4254,7 +4310,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; DPAA2_PMD_INFO("%s: netdev created, connected to %s", - eth_dev->data->name, dpaa2_dev->ep_name); + eth_dev->data->name, priv->ep_name); priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index ed038c204b..acf4a8b320 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -628,18 +628,18 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_MAC) { + if (priv->ep_dev_type == DPAA2_MAC) { /** For dpmac-dpni connection, * try setting serdes loopback as recycle device at first. */ if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; @@ -668,8 +668,8 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_ETH && - dpaa2_dev->object_id == dpaa2_dev->ep_object_id) { + if (priv->ep_dev_type == DPAA2_ETH && + dpaa2_dev->object_id == priv->ep_object_id) { priv->flags |= DPAA2_TX_DPNI_LOOPBACK_MODE; return 0; @@ -682,7 +682,6 @@ int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) { struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct rte_dpaa2_device *dpaa2_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *dpaa2_dev); struct fsl_mc_io *dpni_dev = eth_dev->process_private; struct dpni_port_cfg port_cfg; int ret = 0; @@ -692,7 +691,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) if (priv->flags & DPAA2_TX_SERDES_LOOPBACK_MODE) { if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); @@ -700,7 +699,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 41/45] drivers: align dpaa2 event port depths with hardware rings 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (39 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 40/45] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 42/45] net/dpaa2: read MC version from device private data Prashant Gupta ` (9 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The event port dequeue and enqueue depths were fixed at 8. A dequeue drains the portal DQRR and an enqueue fills the EQCR, so the real limits are the sizes of those two rings, which differ per SoC and are known at run time. Report them instead, adding qbman_swp_portal_dqrr_size() to query the DQRR size (the EQCR size is already available as dpaa2_eqcr_size). The Tx adapter enqueue helpers sized their on-stack mbuf arrays from the advertised enqueue depth, which no longer bounds the burst the adapter may hand them, so bound the copy by the array itself and transmit in chunks. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- .../fslmc/qbman/include/fsl_qbman_portal.h | 7 ++ drivers/bus/fslmc/qbman/qbman_portal.c | 15 ++++ drivers/event/dpaa2/dpaa2_eventdev.c | 72 ++++++++++++------- drivers/event/dpaa2/dpaa2_eventdev.h | 4 +- 4 files changed, 69 insertions(+), 29 deletions(-) diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index 73e57bcdc1..fb1c6046ae 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -1222,6 +1222,13 @@ __rte_internal int qbman_swp_acquire(struct qbman_swp *s, uint16_t bpid, uint64_t *buffers, unsigned int num_buffers); +/** + * qbman_swp_portal_dqrr_size() - Number of entries in a portal's DQRR. + * @p: the software portal object, NULL to query the SoC's DQRR size. + */ +__rte_internal +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p); + /*****************/ /* FQ management */ /*****************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index c95c62baa7..a5f92e27e7 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -73,6 +73,11 @@ enum qbman_sdqcr_fc { static struct qbman_swp *portal_idx_map[MAX_QBMAN_PORTALS]; uint32_t qman_version; +/* DQRR size of the portals initialised so far. All portals of a SoC have the + * same size, so this doubles as the SoC's DQRR size for callers that have no + * portal at hand. + */ +static uint32_t dpaa2_portal_dqrr_size = 8; /* Internal Function declaration */ static int @@ -239,6 +244,15 @@ static int (*qbman_swp_release_ptr)(struct qbman_swp *s, const uint64_t *buffers, unsigned int num_buffers) = qbman_swp_release_direct; +RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_portal_dqrr_size) +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p) +{ + if (p != NULL) + return p->dqrr.dqrr_size; + + return dpaa2_portal_dqrr_size; +} + /*********************************/ /* Portal constructor/destructor */ /*********************************/ @@ -298,6 +312,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) */ p->dqrr.ci_vec_en = true; p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; + dpaa2_portal_dqrr_size = p->dqrr.dqrr_size; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 5d32bd9fd6..ddcf7b3678 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017,2019-2022 NXP + * Copyright 2017,2019-2022,2026 NXP */ #include <assert.h> @@ -389,10 +389,11 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, /* we only support dpio up to number of cores */ if (dev_info->max_event_ports > rte_lcore_count()) dev_info->max_event_ports = rte_lcore_count(); - dev_info->max_event_port_dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - dev_info->max_event_port_enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + /* A dequeue drains the portal DQRR and an enqueue fills the EQCR, so + * the hardware ring sizes are the real limits. + */ + dev_info->max_event_port_dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + dev_info->max_event_port_enqueue_depth = dpaa2_eqcr_size; dev_info->max_num_events = DPAA2_EVENT_MAX_NUM_EVENTS; dev_info->event_dev_cap = RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED | RTE_EVENT_DEV_CAP_ATOMIC | @@ -527,12 +528,9 @@ dpaa2_eventdev_port_def_conf(struct rte_eventdev *dev, uint8_t port_id, RTE_SET_USED(dev); RTE_SET_USED(port_id); - port_conf->new_event_threshold = - DPAA2_EVENT_MAX_NUM_EVENTS; - port_conf->dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - port_conf->enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + port_conf->new_event_threshold = DPAA2_EVENT_MAX_NUM_EVENTS; + port_conf->dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + port_conf->enqueue_depth = dpaa2_eqcr_size; port_conf->event_port_cfg = 0; } @@ -977,18 +975,31 @@ dpaa2_eventdev_txa_enqueue_same_dest(void *port, struct rte_event ev[], uint16_t nb_events) { - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH], *m0; - uint8_t qid, i; + struct rte_mbuf *m[MAX_TX_RING_SLOTS], *m0; + uint16_t sent = 0, burst, i, port_id; + uint8_t qid; RTE_SET_USED(port); - m0 = (struct rte_mbuf *)ev[0].mbuf; + m0 = ev[0].mbuf; qid = rte_event_eth_tx_adapter_txq_get(m0); + port_id = m0->port; + + /* The advertised enqueue depth is the EQCR size, which may exceed the + * on-stack burst array, so transmit in ring-sized chunks. + */ + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) + m[i] = ev[sent + i].mbuf; + + i = rte_eth_tx_burst(port_id, qid, m, burst); + sent += i; + if (i < burst) + break; + } - for (i = 0; i < nb_events; i++) - m[i] = (struct rte_mbuf *)ev[i].mbuf; - - return rte_eth_tx_burst(m0->port, qid, m, nb_events); + return sent; } static uint16_t @@ -996,19 +1007,28 @@ dpaa2_eventdev_txa_enqueue(void *port, struct rte_event ev[], uint16_t nb_events) { - void *txq[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - uint8_t qid, i; + void *txq[MAX_TX_RING_SLOTS]; + struct rte_mbuf *m[MAX_TX_RING_SLOTS]; + uint16_t sent = 0, burst, i; + uint8_t qid; RTE_SET_USED(port); - for (i = 0; i < nb_events; i++) { - m[i] = (struct rte_mbuf *)ev[i].mbuf; - qid = rte_event_eth_tx_adapter_txq_get(m[i]); - txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) { + m[i] = ev[sent + i].mbuf; + qid = rte_event_eth_tx_adapter_txq_get(m[i]); + txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + } + + i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); + sent += i; + if (i < burst) + break; } - return dpaa2_dev_tx_multi_txq_ordered(txq, m, nb_events); + return sent; } static struct eventdev_ops dpaa2_eventdev_ops = { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index 3883a26c91..a054dfdbd7 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017 NXP + * Copyright 2017,2026 NXP */ #ifndef __DPAA2_EVENTDEV_H__ @@ -22,8 +22,6 @@ #define DPAA2_EVENT_MAX_QUEUE_FLOWS 2048 #define DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS 8 #define DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS 0 -#define DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH 8 -#define DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH 8 #define DPAA2_EVENT_MAX_NUM_EVENTS (INT32_MAX - 1) #define DPAA2_EVENT_QUEUE_ATOMIC_FLOWS 2048 -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 42/45] net/dpaa2: read MC version from device private data 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (40 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 41/45] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 43/45] net/dpaa2: do not overwrite mbuf hash with drop priority Prashant Gupta ` (8 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev The flow engine reached back to the bus device to read the MC firmware version. The bus_info pointer behind it is only attached by the primary process, so a secondary process that creates a flow dereferences a pointer it never set up. The version is already cached in priv->mc_rev at probe time and the rest of the driver reads it from there, so use that here too. This removes the last user of DPAA2_DEV_PRIV_TO_DPAA2_DEV(), so drop the macro. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 4 --- drivers/net/dpaa2/dpaa2_flow.c | 59 ++++++++++---------------------- 2 files changed, 18 insertions(+), 45 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 7d93b75be3..e02fa9a622 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -43,10 +43,6 @@ #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 -#define DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv) \ - container_of((((struct dpaa2_dev_priv *)priv)->eth_dev->device), \ - struct rte_dpaa2_device, device) - #define DPAA2_EXTRACT_PARAM_MAX_SIZE \ RTE_ALIGN(sizeof(struct dpni_ext_set_rx_tc_dist), 256) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 8456b3b80d..187381c5dd 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -781,13 +781,10 @@ static int dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, struct dpaa2_generic_flow *flow) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_flow_tbl_profile *tbl_profile; int ret; struct fsl_mc_io *dpni = priv->hw; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - tbl_profile = &priv->flow_profile.tc_profile[flow->tc_id]; if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, flow->entry_index)) { @@ -798,7 +795,7 @@ dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, dpaa2_flow_fs_entry_log("Add", flow); - if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { + if (priv->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token, flow->tc_id, flow->entry_index, &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg); @@ -3642,7 +3639,6 @@ dpaa2_flow_fs_action_config(struct dpaa2_dev_priv *priv, struct dpaa2_generic_flow *flow, const struct rte_flow_action *rte_action) { - struct rte_dpaa2_device *dpaa2_dev; struct rte_eth_dev *dest_dev; struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; @@ -3651,11 +3647,9 @@ dpaa2_flow_fs_action_config(struct dpaa2_dev_priv *priv, uint16_t num_tokens; struct dpaa2_dev_flow_fs_action *fs_action; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - fs_action = &flow->flow_action.fs_action; if (fs_action->action_type != RTE_FLOW_ACTION_TYPE_END) { - if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV && + if (priv->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV && (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR)) { if (rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_ID && @@ -3807,21 +3801,19 @@ dpaa2_flow_fs_table_set_default(struct dpaa2_dev_priv *priv, uint8_t tc_id, int discard, uint16_t default_queue) { int ret; - struct rte_dpaa2_device *dpaa2_dev; struct dpni_rx_dist_cfg *tc_cfg; struct fsl_mc_io *dpni = priv->hw; struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_queue *queue; char mc_rev[1024]; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); tbl_profile = &priv->flow_profile.tc_profile[tc_id]; snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", - RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + RTE_FSL_MC_REV_MAJOR(priv->mc_rev), + RTE_FSL_MC_REV_MINOR(priv->mc_rev), + RTE_FSL_MC_REV_REVISION(priv->mc_rev)); if (!tbl_profile->dpkg.num_extracts && - dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { DPAA2_PMD_DEBUG("%s can't set miss action of FS table indepentently.", mc_rev); return 0; @@ -3946,26 +3938,24 @@ dpaa2_flow_qos_table_set_default(struct dpaa2_dev_priv *priv, int discard, uint8_t default_tc, uint16_t default_flow) { int ret; - struct rte_dpaa2_device *dpaa2_dev; struct dpni_qos_tbl_cfg qos_cfg; struct fsl_mc_io *dpni = priv->hw; struct dpaa2_flow_tbl_profile *tbl_profile; char mc_rev[1024]; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); tbl_profile = &priv->flow_profile.qos_profile; snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", - RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + RTE_FSL_MC_REV_MAJOR(priv->mc_rev), + RTE_FSL_MC_REV_MINOR(priv->mc_rev), + RTE_FSL_MC_REV_REVISION(priv->mc_rev)); if (!tbl_profile->dpkg.num_extracts && - dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { DPAA2_PMD_DEBUG("%s can't set miss action of QoS table indepentently.", mc_rev); return 0; } if (default_flow < priv->dist_queues && - dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) { + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) { DPAA2_PMD_WARN("%s can't direct miss traffic to TC%d-flow%d by QoS table only.", mc_rev, default_tc, default_flow); return 0; @@ -4002,7 +3992,6 @@ static int dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, int rss_dist) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_flow_tbl_profile *tbl_profile; uint8_t *key_cfg_buf; int ret; @@ -4064,8 +4053,7 @@ dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, qos_cfg->discard_on_miss = false; } - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - if (dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) + if (priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, priv->token, qos_cfg); else ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, qos_cfg); @@ -4209,7 +4197,6 @@ static int dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, uint8_t tc_id, const struct rte_flow_action_meter_mark *meter_mark) { - struct rte_dpaa2_device *dpaa2_dev; struct dpni_rx_tc_policing_cfg policing_cfg = {0}; const struct dpaa2_dev_meter_profile *dpaa2_profile; const struct dpaa2_dev_meter_policy *dpaa2_policy = NULL; @@ -4221,8 +4208,6 @@ dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, return -ENOTSUP; } - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - dpaa2_profile = (void *)meter_mark->profile; if (!dpaa2_profile) { DPAA2_PMD_ERR("Meter profile not specified!"); @@ -4244,9 +4229,8 @@ dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, if (priv->flow_profile.mtr_flow[tc_id]) { /** Update existing policer.*/ - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); policing_cfg.options |= DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS; - if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV) + if (priv->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV) DPAA2_PMD_WARN("The existing policer's counters will be cleaned."); } @@ -4269,7 +4253,7 @@ dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, policing_cfg.eir = dpaa2_profile->pir; policing_cfg.ebs = dpaa2_profile->pbs; - if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + if (priv->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, priv->token, tc_id, &policing_cfg); } else { @@ -5400,7 +5384,6 @@ dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev, int mix_extract, int is_rss) { struct dpaa2_generic_flow *flow = NULL; - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_dev_priv *priv = dev->data->dev_private; int ret, idx = -1; uint64_t iova, mc_rev; @@ -5416,8 +5399,7 @@ dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev, if (type != DPAA2_FLOW_QOS_TYPE && type != DPAA2_FLOW_FS_TYPE) return NULL; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - mc_rev = dpaa2_dev->bus_info->mc_rev; + mc_rev = priv->mc_rev; if (actions) { ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions, @@ -5912,19 +5894,17 @@ static int dpaa2_flow_destroy_meter_flow(struct rte_eth_dev *dev, struct dpaa2_dev_flow *flow) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpni_rx_tc_policing_cfg cfg; int ret; uint8_t tc_id; RTE_ASSERT(!flow->qos_flow && flow->fs_flow); - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); tc_id = flow->fs_flow->tc_id; RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow); memset(&cfg, 0, sizeof(cfg)); cfg.mode = DPNI_POLICER_MODE_NONE; - if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + if (priv->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, priv->token, tc_id, &cfg); } else { @@ -6141,7 +6121,6 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, const struct rte_flow_action actions[], struct rte_flow_error *error) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_dev_flow *flow; struct dpaa2_flow_tbl_profile *tbl_profile = NULL; @@ -6162,8 +6141,6 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, const struct rte_flow_action_queue *action_q; struct dpaa2_queue *rxq = NULL; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - /* check for the valid flow */ flow = (void *)_flow; if (flow->is_meter_flow) { @@ -6275,7 +6252,7 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, if (fs_action_num > 0 && fs_actions[0].type != RTE_FLOW_ACTION_TYPE_PORT_ID && fs_actions[0].type != RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT && - dpaa2_dev->bus_info->mc_rev >= DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV) { + priv->mc_rev >= DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV) { /** Action HW update doesn't support redirecting frames to other DPNIs.*/ hw_update = true; goto skip_remove_fs_entry; @@ -6365,7 +6342,7 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, } hw_update = false; - if (dpaa2_dev->bus_info->mc_rev >= DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV) { + if (priv->mc_rev >= DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV) { /** Action HW update doesn't support redirecting frames to other DPNIs.*/ hw_update = true; goto skip_remove_qos_entry; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 43/45] net/dpaa2: do not overwrite mbuf hash with drop priority 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (41 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 42/45] net/dpaa2: read MC version from device private data Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 44/45] bus/fslmc: reduce probe-time logging and MC traffic Prashant Gupta ` (7 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> dpaa2_eth_fd_to_mbuf() wrote the frame descriptor's drop priority into mbuf->hash.sched.color unconditionally. hash.sched shares the union with hash.rss and hash.fdir, so this clobbered whatever the parse step had placed there. The scheduler color is only meaningful when the frame came out of a flow-steering table, and dpaa2_dev_rx_mbuf_sched_set() already sets the whole sched field (queue, traffic class and colour) in that case, so drop the unconditional write. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 5c6a77d2f8..f2137bddd4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -495,7 +495,6 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) mbuf->pkt_len = mbuf->data_len; mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; - mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf), -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 44/45] bus/fslmc: reduce probe-time logging and MC traffic 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (42 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 43/45] net/dpaa2: do not overwrite mbuf hash with drop priority Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-03 13:53 ` [PATCH 45/45] net/dpaa2: reject Rx queue deferred start Prashant Gupta ` (6 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Every DMA map logged its virtual, IOVA and physical addresses at NOTICE. An application that maps many memory segments prints one such line per segment during initialisation, which drowns out messages the operator actually needs; the neighbouring mapping paths already use debug level. fslmc_vfio_get_bus_info() also issued mc_get_soc_version() twice in a row into the same structure, so the second command only overwrote the first result with an identical one. Keep a single query. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/bus/fslmc/fslmc_vfio.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index 4eb8552696..5ccb457a75 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -281,13 +281,6 @@ fslmc_vfio_get_bus_info(void *regs, struct rte_fslmc_bus_info *bus_info) return ret; } - memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); - ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); - if (ret) { - DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); - return ret; - } - for (i = 0; i < RTE_DIM(s_soc_type); i++) { if ((mc_plat_info.svr & DPAA2_SVR_MASK) == s_soc_type[i].svr) { dpaa2_svr_family = s_soc_type[i].svr; @@ -1041,8 +1034,7 @@ fslmc_map_dma(uint64_t vaddr, rte_iova_t iovaddr, size_t len) fslmc_mem_va2iova = RTE_BAD_IOVA; TAILQ_INSERT_TAIL(&fslmc_memsegs, dmaseg, next); } - DPAA2_BUS_LOG(NOTICE, - "%s(%zx): VA(%" PRIx64 "):IOVA(%" PRIx64 "):PHY(%" PRIx64 ")", + DPAA2_BUS_DEBUG("%s(%zx): VA(%" PRIx64 "):IOVA(%" PRIx64 "):PHY(%" PRIx64 ")", is_io ? "DMA I/O map size" : "DMA MEM map size", len, vaddr, iovaddr, phy); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH 45/45] net/dpaa2: reject Rx queue deferred start 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (43 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 44/45] bus/fslmc: reduce probe-time logging and MC traffic Prashant Gupta @ 2026-09-03 13:53 ` Prashant Gupta 2026-09-07 20:35 ` [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Stephen Hemminger ` (5 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-03 13:53 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The driver has no way to hold an Rx queue down while the port is started, and dpaa2_rxq_info_get() already reports rx_deferred_start as 0. The Tx side rejects the request; do the same for Rx instead of silently accepting a configuration that will not be honoured. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 7cd38ddce6..596806c18a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1439,6 +1439,13 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, DPAA2_PMD_DEBUG("dev =%p, queue =%d, pool = %p, conf =%p", dev, rx_queue_id, mb_pool, rx_conf); + /* Rx deferred start is not supported */ + if (rx_conf->rx_deferred_start) { + DPAA2_PMD_ERR("%s: Rx deferred start not supported", + dev->data->name); + return -EINVAL; + } + total_nb_rx_desc += nb_rx_desc; if (total_nb_rx_desc > MAX_NB_RX_DESC_IN_PEB && (priv->options & DPNI_OPT_V1_PFDR_IN_PEB)) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (44 preceding siblings ...) 2026-09-03 13:53 ` [PATCH 45/45] net/dpaa2: reject Rx queue deferred start Prashant Gupta @ 2026-09-07 20:35 ` Stephen Hemminger 2026-09-07 20:47 ` Stephen Hemminger ` (4 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-07 20:35 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 3 Sep 2026 19:23:08 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This series brings the NXP DPAA2 driver stack up to date with the > functionality carried in the NXP internal tree, together with a number of > bug fixes. It covers the crypto (dpaa2_sec), net, dma, mempool, event and > bus/fslmc drivers. Since it was big, ran AI review with Fable. It stopped after finding errors in the first 8 patches. DPAA2 series review (bundle 2096), patches 1-8 of 45 Base: upstream main d55ccd4; all 45 patches apply cleanly with git am --3way. Patch 3: crypto/dpaa2_sec: support AES-GMAC Warning: The patch adds RTE_CRYPTO_AEAD_AES_GMAC to the public enum rte_crypto_aead_algorithm in lib/cryptodev/rte_crypto_sym.h but does not add it to crypto_aead_algorithm_strings[] in lib/cryptodev/rte_cryptodev.c, so rte_cryptodev_get_aead_algo_string() returns NULL for it and rte_cryptodev_get_aead_algo_enum("aes-gmac") fails, which also breaks test-crypto-perf/testpmd-style string selection. There is no entry in doc/guides/rel_notes/release_26_11.rst for the new public API value. The lib/cryptodev change should be its own patch ahead of the driver patch, with the string table and release note. Warning: dpaa2_sec_capabilities[] (the same table returned by rte_cryptodev_info_get() via dpaa2_sec_dev_infos_get) now advertises AES-GMAC as a symmetric AEAD capability, but only the IPsec security path (dpaa2_sec_ipsec_aead_init) handles it; the plain-crypto dpaa2_sec_aead_init() falls into the default case and returns -ENOTSUP. An application that walks rte_cryptodev_sym_capability_get() will find AES-GMAC and then fail session creation. Either advertise it only through the security capability crypto_capabilities or add the plain AEAD path. Patch 6: crypto/dpaa2_sec: add support for env variables Error: The env fallback overrides devargs rather than acting as a fallback. dpaa2_sec_get_devargs() is called twice from dpaa2_sec_dev_init(), once per key: dpaa2_sec_get_devargs(cryptodev, DRIVER_DUMP_MODE); dpaa2_sec_get_devargs(cryptodev, DRIVER_STRICT_ORDER); and the env_set: block reads both environment variables unconditionally: env = getenv(DRIVER_STRICT_ORDER); if (env) internals->en_loose_ordered = !atoi(env); env = getenv(DRIVER_DUMP_MODE); if (env) { dpaa2_sec_dp_dump = atoi(env); With devargs "drv_dump_mode=2" and env drv_dump_mode=0, the first call sets dump mode 2 from devargs and returns; the second call finds no drv_strict_order key, jumps to env_set, and overwrites dpaa2_sec_dp_dump with 0 from the environment. The same happens in the other direction for en_loose_ordered. Read the env vars once after both devargs keys have been processed, and only for keys that were absent from devargs. Warning: getenv() in a driver. Devargs already exist for both of these knobs; per-device runtime configuration belongs in devargs, and checkpatches flags getenv in drivers/ as a forbidden token. Lower-case names like "drv_strict_order" are also unusual for environment variables and easy to confuse with the devargs keys. Patch 7: drivers: fix double free of dpaa2 device on uninit Error: Moving dpaa2_dpdmai_dev_uninit() ahead of rte_dma_pmd_release() in dpaa2_qdma_remove() breaks both teardown orders. dpaa2_dpdmai_dev_uninit(dmadev); ret = rte_dma_pmd_release(dpaa2_dev->device.name); (a) Application called rte_dma_close() before the device is removed (rte_dev_remove / hotplug unplug -> fslmc_bus_unplug_device -> drv->remove). rte_dma_close() -> dma_release() does memset(dev, 0, sizeof(struct rte_dma_dev)), so dpaa2_dev->dmadev points at a zeroed slot and dpaa2_dpdmai_dev_uninit() dereferences dev->data (NULL): struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private; (b) Device removed without a prior close. uninit runs first, does rte_free(qdma_dev) and sets dpdmai_dev->qdma_dev = NULL. Then rte_dma_pmd_release() sees state READY, calls rte_dma_close() -> dpaa2_qdma_close(), which immediately returns: if (!qdma_dev) return 0; so qdma_dev->vqs, the per-VQ fle_pool mempools, ring_cntx_idx and the Rx queue storage are never freed. Before this patch close ran uninit last, after freeing those. Suggested order in remove: if the dmadev is still READY call rte_dma_close() (or dpaa2_qdma_close()) first so the VQ resources are released, then dpdmai_close() the MC object and free qdma_dev, and only then rte_dma_pmd_release(); and guard uninit against a dmadev that has already been released. Info: struct rte_dma_dev is used as a pointer member in bus_fslmc_driver.h without a forward declaration; adding "struct rte_dma_dev;" avoids an implicit file-scope tag declaration inside the struct. Patch 8: net/dpaa2: fix integer overflow in CCSR region mapping Warning: The fix is incomplete. page_size is validated, but the two lines immediately before still use the PAGE_MASK macro, which expands to ~(sysconf(_SC_PAGESIZE) - 1) and is the same unchecked signed value Coverity complained about: start = addr & PAGE_MASK; offset = addr - start; len = len & PAGE_MASK; Compute a local mask from the validated page_size (e.g. uint64_t page_mask = ~((uint64_t)page_size - 1)) and use it for start and len; the later "len & ~(page_size - 1)" is then redundant with the earlier "len = len & PAGE_MASK". Review-Result: ERROR ^ permalink raw reply [flat|nested] 356+ messages in thread
* Re: [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (45 preceding siblings ...) 2026-09-07 20:35 ` [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Stephen Hemminger @ 2026-09-07 20:47 ` Stephen Hemminger 2026-09-07 21:03 ` Stephen Hemminger ` (3 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-07 20:47 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 3 Sep 2026 19:23:08 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This series brings the NXP DPAA2 driver stack up to date with the > functionality carried in the NXP internal tree, together with a number of > bug fixes. It covers the crypto (dpaa2_sec), net, dma, mempool, event and > bus/fslmc drivers. > > Fixes first, then features, so the bug fixes can be picked independently of > the larger reworks. Another round of errors detected by Fable against 9-20. DPAA2 series review (bundle 2096), patches 9-20 of 45 Base: upstream main d55ccd4; series applied with git am --3way. Patch 9: dma/dpaa2: fix array-bounds warning in dequeue path Warning: The warning this patch fixes does not exist at this point in the series. At patch 9, qdma_cntx_idx_ring_eq() is still the per-element loop: for (i = 0; i < nb; i++) { ring->cntx_idx_ring[ring->tail] = elem[i]; and passing &idx with nb == 1 indexes elem[0] only. The -Warray-bounds diagnostic comes from the rte_memcpy rewrite in patch 12, which forms &elem[DPAA2_QDMA_MAX_DESC - ring->tail] on a one-element object in the wrap-around branch. So this is not a fix for 388e888dc082 and should not carry Fixes:/Cc: stable; it belongs with patch 12. The fix itself is heavy: DPAA2_QDMA_MAX_DESC is ((1 << 13) / 2) = 4096, so uint16_t idxs[DPAA2_QDMA_MAX_DESC]; adds 8 KB to every struct qdma_virt_queue and only idxs[0] is ever written. Handle the single-index case in ring_eq instead, e.g. compute first = RTE_MIN(nb, DPAA2_QDMA_MAX_DESC - ring->tail), copy first elements, and only touch elem + first when nb > first, which also gives the compiler a bound it can prove. Patch 11: dma/dpaa2: validate IOVA in pre-populate helpers Error: The new early returns leak the fle_pool element in non-silent mode. In dpaa2_qdma_copy_sg(): ret = rte_mempool_get(qdma_vq->fle_pool, (void **)&cntx_sg); ... ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); if (ret) return ret; and in dpaa2_qdma_long_copy(): ret = rte_mempool_get(qdma_vq->fle_pool, (void **)&fle_sdd); ... ret = fle_sdd_pre_populate(fle_sdd, &qdma_vq->rbp, 0, 0, QBMAN_FLE_WORD4_FMT_SBF); if (ret) return ret; Neither path returns the context to the pool. Each failed enqueue permanently consumes one fle_pool element. Add rte_mempool_put() on the error path when !is_silent (the silent path uses the pre-allocated cntx_sg[]/cntx_fle_sdd[] arrays and needs no free). Patch 13: drivers: add dpaa2 DMA bypass memory translation option Error: RTE_DPAAX_QDMA_BMT_FLAG is only partially honoured. (a) In the pre-populate SG path the flag is applied once, when the context is first initialised: if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq, (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); sg_entry_post_populate() never writes ctrl.bmt, so every later job that picks this context out of fle_pool inherits whatever the first job asked for, regardless of its own flags. (b) The long-FD path ignores the flag entirely. Neither fle_sdd_pre_populate() nor fle_populate() takes a bmt argument and nothing sets fle->word4.bmt, so on a vchan with using_short_fd == 0 (dpaa2_qdma_long_copy) the flag has no effect. The commit message says the flag is propagated to all FD populate helpers; it is not. Warning: RTE_DPAAX_QDMA_BMT_FLAG is a new public API in an installed header (drivers/common/dpaax/meson.build lists rte_pmd_dpaax_qdma.h in headers) with no Doxygen comment, no mention in doc/guides/dmadevs/dpaa2.rst, and no release note. It also occupies bit 7, immediately below the RTE_DPAAX_QDMA index bits at 8+, and immediately above the generic RTE_DMA_OP_FLAG_* bits (0-3), so a future generic flag at bit 4-7 collides with it. Patch 14: mempool/dpaa2: support ops index from primary in secondary Error: rte_dpaa2_mpool_get_ops_idx() returns the wrong value on the first successful IPC round trip in a secondary: if (rsp_msg->msg_type == DPAA2_POOL_OPS_IDX_RSP) { rte_memcpy(&s_dpaa2_pool_ops_idx, rsp_msg->msg_data, sizeof(s_dpaa2_pool_ops_idx)); ret = 0; } ... free(mp_reply.msgs); return ret; It returns 0 instead of s_dpaa2_pool_ops_idx. Every caller compares the result against mb_pool->ops_index (dpaa2_sec enqueue, net Tx), so the first packet burst in a secondary process gets a false mismatch and takes the MAX_BPID path. Return s_dpaa2_pool_ops_idx on success. Error: mp_req is an uninitialised stack struct: struct rte_mp_msg mp_req; ... strlcpy(mp_req.name, DPAA2_POOL_MP_SYNC, sizeof(mp_req.name)); req_msg->msg_type = DPAA2_POOL_OPS_IDX_REQ; ... ret = rte_mp_request_sync(&mp_req, &mp_reply, &ts); len_param and num_fds are never set. check_input() in eal_common_proc.c rejects negative or oversized values, and send_msg() attaches num_fds entries of fds[] as SCM_RIGHTS, so with stack garbage the request either fails outright or sends random descriptors. memset the request to zero and set mp_req.len_param = sizeof(struct dpaa2_pool_mp_msg) + sizeof(s_dpaa2_pool_ops_idx). The primary-side reply has the matching problem: reply is zeroed but reply.len_param stays 0 while param carries the ops index. Error: Resource leak on the new failure path in rte_hw_mbuf_create_pool(): ret = rte_mp_action_register(DPAA2_POOL_MP_SYNC, dpaa2_mbuf_pool_mp_primary); if (ret && rte_errno != ENOTSUP) return ret; At this point bp_list and bp_info are allocated, the dpbp is enabled and avail_dpbp is taken; every other failure in this function uses goto err4. Replace the return with goto err4. rte_mp_action_register() also returns -1 with the reason in rte_errno, so the caller sees a bare -1; return -rte_errno. Warning: rte_memcpy() for a 2-byte copy on the IPC control path (both in the handler and in the requester); use memcpy(). Patch 16: drivers: optimize dpaa2 Tx queue and channel mapping Error: The new capping logic is defeated by uint8_t truncation. priv->nb_rx_queues and priv->nb_tx_queues are uint8_t, and attr.num_rx_tcs, attr.num_tx_tcs and attr.num_queues are uint8_t: priv->nb_rx_queues = attr.num_rx_tcs * attr.num_queues; if (priv->nb_rx_queues > MAX_RX_QUEUES) { ... priv->nb_tx_queues = attr.num_tx_tcs * attr.num_queues; if (priv->nb_tx_queues > MAX_TX_QUEUES) { The product is computed as int and truncated to 8 bits on assignment before the comparison, so a DPNI with 8 TCs and 32 queues per TC (256) yields nb_rx_queues = nb_tx_queues = 0 and the "Too many" branch never fires. Compute into a uint32_t local, cap, then assign. The TX side is new in this patch (the old value was num_tx_tcs * num_channels, which cannot overflow); the RX side overflowed before too but is rewritten here. Related: capping the total to 128 rather than the per-TC count makes tc_index = i / (128 / num_tx_tc) exceed num_tx_tc when num_tx_tc does not divide 128 (e.g. 3 TCs -> per_tc 42, i = 126, 127 map to TC 3). Cap num_queue_per_tc instead and derive the totals from that. Error: The new early return in dpaa2_dev_rx_queue_setup() breaks Rx queue reconfiguration: if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", dev->data->name, rx_queue_id); dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } dpaa2_dev_rx_queue_release() does not reset fqid to DPAA2_INVALID_FQ_ID, so the stop / reconfigure / rx_queue_setup sequence that rte_eth_rx_queue_setup() performs (release, then setup) hits this return and silently keeps the old mb_pool, nb_desc and offloads. Worse, release cleared the CGID (priv->cgid_in_use[cgid] = 0; dpaa2_q->cgid = DPAA2_INVALID_CGID) and the early return skips the block that allocates a new one and programs taildrop / congestion notification, so the queue runs without its drop configuration after any reconfigure. Either reset fqid in rx_queue_release, or drop the early return on the Rx side (the Tx side had the same pattern before this patch via DPAA2_INVALID_FLOW_ID, and tx_queue_release should be checked for the same reason). Patch 17: net/dpaa2: support larger burst size Warning: The version gate excludes newer major versions: if (priv->dpni_ver_major == 8 && priv->dpni_ver_minor >= 7) A DPNI API 9.x would fall back to 64 KB. dpaa2_ethdev.h already has dpaa2_dev_cmp_dpni_ver(priv, major, minor); use dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0. Warning: The new header comment and the code disagree on the non-LX2160A limit. fsl_dpni.h says: * @max_burst_size: Burst size in bytes. Limits depend on the SoC * (0x37FFF for LX2160A, 0xF7FF for all others) but dpaa2_get_burst_max() returns (64 * 1024) = 0x10000 for "all others", which is above 0xF7FF. One of the two is wrong. Patch 18: net/dpaa2: support MPLS and PPPoE flow distribution Warning: doc/guides/nics/features/dpaa2.ini is not updated; the [rte_flow items] section needs mpls and pppoes entries for the new pattern support. Patch 19: net/dpaa2: support meter and policing Error: dpaa2_mtr_ops_get() re-initialises the lock on every call: int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) { struct dpaa2_dev_priv *priv = dev->data->dev_private; rte_spinlock_init(&priv->meter_lock); rte_mtr_ops_get() in lib/ethdev/rte_mtr.c calls dev->dev_ops->mtr_ops_get() at the start of every rte_mtr_*() API call, so any concurrent rte_mtr call resets a spinlock that another thread may currently hold, and the list manipulation it protects is then unprotected. Initialise the lock once in dpaa2_dev_init() next to the LIST_HEAD fields. Warning: dpaa2_mtr_profile_delete() and dpaa2_mtr_policy_delete() walk priv->meters and silently free every meter that references the profile/policy: if (meter->profile_id == profile_id) { ... LIST_REMOVE(tmp, next); rte_free(tmp); rte_mtr.h documents both operations as failing when at least one MTR object still uses the profile/policy. Return -EBUSY instead; otherwise the application keeps a meter id that no longer exists and any flow created with it (patch 37 wires meters into dpni_set_rx_tc_policing) is left pointing at a freed object. Warning: No documentation for the new feature: nothing in doc/guides/nics/features/dpaa2.ini, doc/guides/nics/dpaa2.rst, or the 26.11 release notes. (The series as a whole adds nothing under doc/.) Info: In dpaa2_mtr_profile_add(): } else if (profile->packet_mode > DPNI_POLICER_UNIT_FRAMES) { dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS; rte_mtr_meter_profile.packet_mode is a 0/1 flag and DPNI_POLICER_UNIT_FRAMES is 1, so this branch is unreachable. Info: s_err_msg is a single static buffer shared by every port and thread, and its address is handed to the caller via rte_mtr_error_set(); concurrent callers can see each other's message. dpaa2_mtr_policy_add() returns ENOMEM for "action not supported" (should be ENOTSUP), and dpaa2_mtr_profile_add() returns -ENOTSUP without filling in *error. struct dpaa2_dev_meter_policy's red_drop is an int holding a bool. Review-Result: ERROR ^ permalink raw reply [flat|nested] 356+ messages in thread
* Re: [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (46 preceding siblings ...) 2026-09-07 20:47 ` Stephen Hemminger @ 2026-09-07 21:03 ` Stephen Hemminger 2026-09-07 21:10 ` Stephen Hemminger ` (2 subsequent siblings) 50 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-07 21:03 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 3 Sep 2026 19:23:08 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This series brings the NXP DPAA2 driver stack up to date with the > functionality carried in the NXP internal tree, together with a number of > bug fixes. It covers the crypto (dpaa2_sec), net, dma, mempool, event and > bus/fslmc drivers. > > Fixes first, then features, so the bug fixes can be picked independently of > the larger reworks. And the errors caught by Fable continue in Patch 21-32 DPAA2 series review (bundle 2096), patches 9-20 of 45 Base: upstream main d55ccd4; series applied with git am --3way. Patch 9: dma/dpaa2: fix array-bounds warning in dequeue path Warning: The warning this patch fixes does not exist at this point in the series. At patch 9, qdma_cntx_idx_ring_eq() is still the per-element loop: for (i = 0; i < nb; i++) { ring->cntx_idx_ring[ring->tail] = elem[i]; and passing &idx with nb == 1 indexes elem[0] only. The -Warray-bounds diagnostic comes from the rte_memcpy rewrite in patch 12, which forms &elem[DPAA2_QDMA_MAX_DESC - ring->tail] on a one-element object in the wrap-around branch. So this is not a fix for 388e888dc082 and should not carry Fixes:/Cc: stable; it belongs with patch 12. The fix itself is heavy: DPAA2_QDMA_MAX_DESC is ((1 << 13) / 2) = 4096, so uint16_t idxs[DPAA2_QDMA_MAX_DESC]; adds 8 KB to every struct qdma_virt_queue and only idxs[0] is ever written. Handle the single-index case in ring_eq instead, e.g. compute first = RTE_MIN(nb, DPAA2_QDMA_MAX_DESC - ring->tail), copy first elements, and only touch elem + first when nb > first, which also gives the compiler a bound it can prove. Patch 11: dma/dpaa2: validate IOVA in pre-populate helpers Error: The new early returns leak the fle_pool element in non-silent mode. In dpaa2_qdma_copy_sg(): ret = rte_mempool_get(qdma_vq->fle_pool, (void **)&cntx_sg); ... ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); if (ret) return ret; and in dpaa2_qdma_long_copy(): ret = rte_mempool_get(qdma_vq->fle_pool, (void **)&fle_sdd); ... ret = fle_sdd_pre_populate(fle_sdd, &qdma_vq->rbp, 0, 0, QBMAN_FLE_WORD4_FMT_SBF); if (ret) return ret; Neither path returns the context to the pool. Each failed enqueue permanently consumes one fle_pool element. Add rte_mempool_put() on the error path when !is_silent (the silent path uses the pre-allocated cntx_sg[]/cntx_fle_sdd[] arrays and needs no free). Patch 13: drivers: add dpaa2 DMA bypass memory translation option Error: RTE_DPAAX_QDMA_BMT_FLAG is only partially honoured. (a) In the pre-populate SG path the flag is applied once, when the context is first initialised: if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq, (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); sg_entry_post_populate() never writes ctrl.bmt, so every later job that picks this context out of fle_pool inherits whatever the first job asked for, regardless of its own flags. (b) The long-FD path ignores the flag entirely. Neither fle_sdd_pre_populate() nor fle_populate() takes a bmt argument and nothing sets fle->word4.bmt, so on a vchan with using_short_fd == 0 (dpaa2_qdma_long_copy) the flag has no effect. The commit message says the flag is propagated to all FD populate helpers; it is not. Warning: RTE_DPAAX_QDMA_BMT_FLAG is a new public API in an installed header (drivers/common/dpaax/meson.build lists rte_pmd_dpaax_qdma.h in headers) with no Doxygen comment, no mention in doc/guides/dmadevs/dpaa2.rst, and no release note. It also occupies bit 7, immediately below the RTE_DPAAX_QDMA index bits at 8+, and immediately above the generic RTE_DMA_OP_FLAG_* bits (0-3), so a future generic flag at bit 4-7 collides with it. Patch 14: mempool/dpaa2: support ops index from primary in secondary Error: rte_dpaa2_mpool_get_ops_idx() returns the wrong value on the first successful IPC round trip in a secondary: if (rsp_msg->msg_type == DPAA2_POOL_OPS_IDX_RSP) { rte_memcpy(&s_dpaa2_pool_ops_idx, rsp_msg->msg_data, sizeof(s_dpaa2_pool_ops_idx)); ret = 0; } ... free(mp_reply.msgs); return ret; It returns 0 instead of s_dpaa2_pool_ops_idx. Every caller compares the result against mb_pool->ops_index (dpaa2_sec enqueue, net Tx), so the first packet burst in a secondary process gets a false mismatch and takes the MAX_BPID path. Return s_dpaa2_pool_ops_idx on success. Error: mp_req is an uninitialised stack struct: struct rte_mp_msg mp_req; ... strlcpy(mp_req.name, DPAA2_POOL_MP_SYNC, sizeof(mp_req.name)); req_msg->msg_type = DPAA2_POOL_OPS_IDX_REQ; ... ret = rte_mp_request_sync(&mp_req, &mp_reply, &ts); len_param and num_fds are never set. check_input() in eal_common_proc.c rejects negative or oversized values, and send_msg() attaches num_fds entries of fds[] as SCM_RIGHTS, so with stack garbage the request either fails outright or sends random descriptors. memset the request to zero and set mp_req.len_param = sizeof(struct dpaa2_pool_mp_msg) + sizeof(s_dpaa2_pool_ops_idx). The primary-side reply has the matching problem: reply is zeroed but reply.len_param stays 0 while param carries the ops index. Error: Resource leak on the new failure path in rte_hw_mbuf_create_pool(): ret = rte_mp_action_register(DPAA2_POOL_MP_SYNC, dpaa2_mbuf_pool_mp_primary); if (ret && rte_errno != ENOTSUP) return ret; At this point bp_list and bp_info are allocated, the dpbp is enabled and avail_dpbp is taken; every other failure in this function uses goto err4. Replace the return with goto err4. rte_mp_action_register() also returns -1 with the reason in rte_errno, so the caller sees a bare -1; return -rte_errno. Warning: rte_memcpy() for a 2-byte copy on the IPC control path (both in the handler and in the requester); use memcpy(). Patch 16: drivers: optimize dpaa2 Tx queue and channel mapping Error: The new capping logic is defeated by uint8_t truncation. priv->nb_rx_queues and priv->nb_tx_queues are uint8_t, and attr.num_rx_tcs, attr.num_tx_tcs and attr.num_queues are uint8_t: priv->nb_rx_queues = attr.num_rx_tcs * attr.num_queues; if (priv->nb_rx_queues > MAX_RX_QUEUES) { ... priv->nb_tx_queues = attr.num_tx_tcs * attr.num_queues; if (priv->nb_tx_queues > MAX_TX_QUEUES) { The product is computed as int and truncated to 8 bits on assignment before the comparison, so a DPNI with 8 TCs and 32 queues per TC (256) yields nb_rx_queues = nb_tx_queues = 0 and the "Too many" branch never fires. Compute into a uint32_t local, cap, then assign. The TX side is new in this patch (the old value was num_tx_tcs * num_channels, which cannot overflow); the RX side overflowed before too but is rewritten here. Related: capping the total to 128 rather than the per-TC count makes tc_index = i / (128 / num_tx_tc) exceed num_tx_tc when num_tx_tc does not divide 128 (e.g. 3 TCs -> per_tc 42, i = 126, 127 map to TC 3). Cap num_queue_per_tc instead and derive the totals from that. Error: The new early return in dpaa2_dev_rx_queue_setup() breaks Rx queue reconfiguration: if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", dev->data->name, rx_queue_id); dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } dpaa2_dev_rx_queue_release() does not reset fqid to DPAA2_INVALID_FQ_ID, so the stop / reconfigure / rx_queue_setup sequence that rte_eth_rx_queue_setup() performs (release, then setup) hits this return and silently keeps the old mb_pool, nb_desc and offloads. Worse, release cleared the CGID (priv->cgid_in_use[cgid] = 0; dpaa2_q->cgid = DPAA2_INVALID_CGID) and the early return skips the block that allocates a new one and programs taildrop / congestion notification, so the queue runs without its drop configuration after any reconfigure. Either reset fqid in rx_queue_release, or drop the early return on the Rx side (the Tx side had the same pattern before this patch via DPAA2_INVALID_FLOW_ID, and tx_queue_release should be checked for the same reason). Patch 17: net/dpaa2: support larger burst size Warning: The version gate excludes newer major versions: if (priv->dpni_ver_major == 8 && priv->dpni_ver_minor >= 7) A DPNI API 9.x would fall back to 64 KB. dpaa2_ethdev.h already has dpaa2_dev_cmp_dpni_ver(priv, major, minor); use dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0. Warning: The new header comment and the code disagree on the non-LX2160A limit. fsl_dpni.h says: * @max_burst_size: Burst size in bytes. Limits depend on the SoC * (0x37FFF for LX2160A, 0xF7FF for all others) but dpaa2_get_burst_max() returns (64 * 1024) = 0x10000 for "all others", which is above 0xF7FF. One of the two is wrong. Patch 18: net/dpaa2: support MPLS and PPPoE flow distribution Warning: doc/guides/nics/features/dpaa2.ini is not updated; the [rte_flow items] section needs mpls and pppoes entries for the new pattern support. Patch 19: net/dpaa2: support meter and policing Error: dpaa2_mtr_ops_get() re-initialises the lock on every call: int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) { struct dpaa2_dev_priv *priv = dev->data->dev_private; rte_spinlock_init(&priv->meter_lock); rte_mtr_ops_get() in lib/ethdev/rte_mtr.c calls dev->dev_ops->mtr_ops_get() at the start of every rte_mtr_*() API call, so any concurrent rte_mtr call resets a spinlock that another thread may currently hold, and the list manipulation it protects is then unprotected. Initialise the lock once in dpaa2_dev_init() next to the LIST_HEAD fields. Warning: dpaa2_mtr_profile_delete() and dpaa2_mtr_policy_delete() walk priv->meters and silently free every meter that references the profile/policy: if (meter->profile_id == profile_id) { ... LIST_REMOVE(tmp, next); rte_free(tmp); rte_mtr.h documents both operations as failing when at least one MTR object still uses the profile/policy. Return -EBUSY instead; otherwise the application keeps a meter id that no longer exists and any flow created with it (patch 37 wires meters into dpni_set_rx_tc_policing) is left pointing at a freed object. Warning: No documentation for the new feature: nothing in doc/guides/nics/features/dpaa2.ini, doc/guides/nics/dpaa2.rst, or the 26.11 release notes. (The series as a whole adds nothing under doc/.) Info: In dpaa2_mtr_profile_add(): } else if (profile->packet_mode > DPNI_POLICER_UNIT_FRAMES) { dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS; rte_mtr_meter_profile.packet_mode is a 0/1 flag and DPNI_POLICER_UNIT_FRAMES is 1, so this branch is unreachable. Info: s_err_msg is a single static buffer shared by every port and thread, and its address is handed to the caller via rte_mtr_error_set(); concurrent callers can see each other's message. dpaa2_mtr_policy_add() returns ENOMEM for "action not supported" (should be ENOTSUP), and dpaa2_mtr_profile_add() returns -ENOTSUP without filling in *error. struct dpaa2_dev_meter_policy's red_drop is an int holding a bool. Review-Result: ERROR ^ permalink raw reply [flat|nested] 356+ messages in thread
* Re: [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (47 preceding siblings ...) 2026-09-07 21:03 ` Stephen Hemminger @ 2026-09-07 21:10 ` Stephen Hemminger 2026-09-07 21:22 ` Stephen Hemminger 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta 50 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-07 21:10 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 3 Sep 2026 19:23:08 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This series brings the NXP DPAA2 driver stack up to date with the > functionality carried in the NXP internal tree, together with a number of > bug fixes. It covers the crypto (dpaa2_sec), net, dma, mempool, event and > bus/fslmc drivers. Recommendation, break this up. There are too many errors to allow merging now. But if you break it up some of the chunks might be ok. For example: send the bug fixes only as short series. The problem is you are working away from upstream. That process will exhaust you because you end up fixing things in multiple places. For example: patch 24 removes a guard that 57b8ce0 added upstream in July ^ permalink raw reply [flat|nested] 356+ messages in thread
* Re: [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (48 preceding siblings ...) 2026-09-07 21:10 ` Stephen Hemminger @ 2026-09-07 21:22 ` Stephen Hemminger 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta 50 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-07 21:22 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 3 Sep 2026 19:23:08 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This series brings the NXP DPAA2 driver stack up to date with the > functionality carried in the NXP internal tree, together with a number of > bug fixes. It covers the crypto (dpaa2_sec), net, dma, mempool, event and > bus/fslmc drivers. > > Fixes first, then features, so the bug fixes can be picked independently of > the larger reworks. AI found errors in last set: DPAA2 series review (bundle 2096), patches 32-45 of 45 Base: upstream main d55ccd4; series applied with git am --3way. Findings for 32 supersede the partial entry in the 21-32 review. Patch 32: drivers: rework dpaa2 Tx confirmation Error: priv->tx_sg_pool is never assigned. The patch adds the field to struct dpaa2_dev_priv and reads it in dpaa2_dev_tx_mbuf_to_sg_fd(): sg_mbuf = NULL; if (priv->tx_sg_pool) sg_mbuf = rte_pktmbuf_alloc(priv->tx_sg_pool); if (!sg_mbuf) { DPAA2_PMD_DP_DEBUG("No memory to allocate S/G table"); return -ENOMEM; } but dpaa2_tx_sg_pool_init() only sets the file-scope global dpaa2_tx_sg_pool, and a grep of the final tree finds no store to the priv member. priv is zero-allocated, so every multi-segment Tx whose head mbuf cannot host the SG table in its own headroom (any non-hw-pool head, any indirect head, or too little headroom) fails with -ENOMEM. The old code used dpaa2_tx_sg_pool directly. Error: Per-packet failures free the application's mbuf and then report it as not sent. In dpaa2_dev_tx_mbuf_to_simple_fd(): } else { copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(mbuf, hw_mp); if (!copy_mbuf) { ret = -ENOMEM; goto quit; } DPAA2_MBUF_TO_CONTIG_FD(copy_mbuf, fd, mempool_to_bpid(hw_mp)); quit: rte_pktmbuf_free(mbuf); } and in dpaa2_dev_tx(): ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); ... if (ret) goto send_n_return; send_n_return enqueues fd_arr[0..loop-1] and returns that count, so the packet at index loop is excluded from the return value after the driver has already freed it; the application retries it and double-frees. The same happens in dpaa2_dev_tx_multi_txq_ordered() via send_frames. The cloned-mbuf branch just above it has the same shape: the indirect mbuf is re-initialised and freed before the copy is attempted. And dpaa2_dev_tx_no_conf_mbuf_to_sge() can return -ENOMEM part way through a chain after it has already replaced earlier segments, relinked prev->next, and decremented refcounts on segments with refcnt > 1; that mutated chain is then handed back to the application as unsent, and the sg_mbuf taken from tx_sg_pool in the caller is leaked. A per-packet failure must either drop the packet (free it, count it in err_pkts, continue) or leave it untouched and return short; doing both is a double free. Error: The DQRR held-buffer bitmap update regresses a 64-bit shift: DPAA2_PER_LCORE_DQRR_HELD &= ~(1 << dqrr_index); The line this replaces was ~(UINT64_C(1) << dqrr_index), and the other three sites in the file still use UINT64_C(1). dqrr_held is uint64_t and dqrr_index reaches 31 on LX2160A (DPAA2_LX2_DQRR_RING_SIZE is 32, and patch 41 raises the event port dequeue depth to that), so 1 << 31 is int, sign-extends, and the ~ clears bits 0..30 of the upper word as well. Warning: New devargs drv_tx_dyn_conf and drv_tx_dyn_conf_pre are added and drv_tx_conf now means "absolute confirmation", but doc/guides/nics/dpaa2.rst, which documents drv_tx_conf, is untouched. Warning: dpaa2_eth_fd_to_mbuf() and dpaa2_eth_sg_fd_to_mbuf() are annotated __rte_internal in dpaa2_ethdev.h. That attribute is for symbols exported with RTE_EXPORT_INTERNAL_SYMBOL; these are used only inside the net driver. Info: dpaa2_dev_tx_conf() releases a head mbuf with refcnt > 1 by rte_mbuf_refcnt_update(m, -1) instead of rte_pktmbuf_free(m), so the tail segments of such a chain are never walked. rte_pktmbuf_free() handles each segment's refcount itself; the special case is not needed. Patch 33: net/dpaa2: ptp enhancements Error: Two exported experimental APIs are deleted without deprecation and without removing their declarations. The definitions of rte_pmd_dpaa2_set_one_step_ts() and rte_pmd_dpaa2_get_one_step_ts() (both RTE_EXPORT_EXPERIMENTAL_SYMBOL, 24.11) are removed from dpaa2_ethdev.c and not re-added anywhere; the prototypes remain in the installed header rte_pmd_dpaa2.h, so any consumer now fails at link time. Either keep the symbols (wrapping the new dpaa2_timesync_set_one_step()) or remove the prototypes and add a "Removed Items" release note. Warning: getenv("DPAA2_IEEE1588_DEBUG_ENABLE") in dpaa2_timesync_enable(); use a devargs or log level. Patch 35: net/dpaa2: update MC dpni QoS and flow steering API Warning: The existing callers are switched to newer MC command versions with no version gate. DPNI_CMDID_ADD_FS_ENT becomes DPNI_CMD_V3, DPNI_CMDID_SET_QOS_TBL becomes DPNI_CMD_V3 and DPNI_CMDID_SET_RX_TC_POLICING becomes DPNI_CMD_V2, and the flow code at this point still calls dpni_add_fs_entry() and dpni_set_qos_table() unconditionally, so on an MC that predates those command versions every existing flow rule fails. The commit message says behaviour is unchanged. Patch 37 adds the priv->mc_rev gating (DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV etc.); it belongs in this patch, next to the version bump. Patch 36: net/dpaa2: enhance xstat implementation Error: dpaa2_dev_xstats_get_by_id() does not bound the number of MAC counters it collects: uint64_t *mac_val[DPAA2_MAC_XSTAT_MAX_NUM]; ... for (i = 0; i < n; i++) { ... if (id >= DPAA2_MAC_XSTATS_START_ID) { values[i] = 0; if (dpaa2_dev_mac_xstats_avail(dev)) { mac_idx[mac_num] = rte_cpu_to_le_32(id - DPAA2_MAC_XSTATS_START_ID); mac_val[mac_num] = &values[i]; mac_num++; } ids[] is application-supplied and may repeat an id, so n MAC ids overflow mac_val[] on the stack and the fixed-size cnt_idx_dma_mem / cnt_values_dma_mem buffers. Check mac_num < DPAA2_MAC_XSTAT_MAX_NUM before the stores. Warning: dpaa2_dev_xstats_get_names() returns limit when limit is smaller than the count: if (limit < stat_cnt) stat_cnt = limit; The eth_xstats_get_names_t contract is to return the number of available xstats when xstats_names is NULL or size is too small, so the caller can resize. Same in dpaa2_dev_xstats_get() when n is smaller than the count. Warning: rte_memcpy() of the string-pointer table (dpaa2_xstats_strings) on the control path in both get_names functions; memcpy, or index the struct directly. Patch 37: net/dpaa2: rework flow engine Warning: The QoS/FS group-type machinery is unreachable upstream: #ifndef RTE_DPAA2_FLOW_GROUP_TYPE_GET #define RTE_DPAA2_FLOW_GROUP_TYPE_GET(group) \ ((void)(group), RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) #endif Nothing in the tree defines the real macros, so RTE_DPAA2_QOS_GROUP_FLOW / RTE_DPAA2_FS_GROUP_FLOW and every branch keyed on them in dpaa2_flow_create() are dead code kept alive for an out-of-tree header. Either define the encoding in rte_pmd_dpaa2.h and document it, or drop the group-type paths. Warning: getenv("DPAA2_FLOW_CONTROL_LOG") is kept (now read on every rte_flow_create()); use the log level. Warning: dpaa2_flow.c goes from 1 to 13 rte_memcpy() calls, all on the flow-create control path (e.g. rte_memcpy(&local_attr, attr, sizeof(struct rte_flow_attr))); use memcpy. Warning: No doc/guides/nics/features/dpaa2.ini update for the new meter_mark action, and no dpaa2.rst description of the group encoding, meter flows, or the MC-version-dependent behaviour. Patch 38: net/dpaa2: support Rx mempool per traffic class Error: The pool-to-TC association is programmed with the TC index where the MC expects a bitmask: bpool_cfg->pools[bp_idx].priority_mask = tc_id; fsl_dpni.h documents pools.priority as "Priority mask that indicates TC's used with this buffer. If set to 0x00 MC will assume value 0xff". With tc_id: TC0 gets mask 0 (= all TCs), TC1 gets 0x01 (= TC0), TC2 gets 0x02 (= TC1), and so on, so the isolation the commit describes does not happen and TC0's pool is shared by everyone. Use RTE_BIT32(tc_id). Patch 39: drivers: consume dpaa2 DQRR entries in batches Error: The consume vector cannot represent an LX2160A DQRR. The patch's own comment says the vector occupies DCAP bits 16..31, i.e. 16 index bits, and the code does: s->dqrr.ci_vector |= RTE_BIT32(idx + DQRR_DCAP_CI_VEC_OFFSET); with ci_vector a uint32_t. DPAA2_LX2_DQRR_RING_SIZE is 32, so idx is 0..31 and idx + 16 is 16..47; for idx >= 16 that is a shift of 32 or more, undefined behaviour, and the entry is never consumed. Either the register is wider than the comment says, or vector mode must only be enabled when dqrr_size <= 16 (with the threshold derived accordingly). Patch 42: net/dpaa2: read MC version from device private data Info: This only replaces the DPAA2_DEV_PRIV_TO_DPAA2_DEV() accessor that patch 37 introduced five patches earlier; fold it into 37. Patch 44: bus/fslmc: reduce probe-time logging and MC traffic Info: The duplicated mc_get_soc_version() call this removes was added by patch 27 in the same series; fold it into 27. Review-Result: ERROR ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v2 00/47] NXP DPAA2 driver updates and fixes 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta ` (49 preceding siblings ...) 2026-09-07 21:22 ` Stephen Hemminger @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 01/47] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta ` (47 more replies) 50 siblings, 48 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev This series brings the NXP DPAA2 drivers (net, crypto, dma, event, mempool and the fslmc bus) up to date with the current internal tree. It carries bug fixes, a reworked flow engine, an extended parser, meter and policer support, PTP enhancements, and a number of performance improvements in the Rx/Tx and DQRR handling paths. The series is based on commit c1a46b9d9243 and is intended for 26.11. Changes in v2: - Dropped the header-only patches; every remaining patch now contains the implementation together with its declarations. - Addressed all findings reported by checkpatch; the series is clean against the current checkpatch. - Removed the per-device Tx scatter/gather pool member that was never assigned, and used the existing global pool instead. - Widened the DQRR held-mask shift to 64-bit to avoid undefined behaviour when the DQRR index exceeds 31. - Bounded the MAC xstats collection loop by the size of the statistics array. - Treated the traffic class priority mask as a bitmask rather than an index. - Added a per-entry DQRR consume fallback for portals whose DQRR ring does not fit the vectored consume encoding. Each of the review fixes above has been folded into the patch that introduced the code in question, so the series remains bisectable. Build tested with gcc, clang and the aarch64 DPAA cross toolchain (werror enabled, no compiler warnings). Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Gagandeep Singh (18): crypto/dpaa2_sec: fix buffer overflow in GCM decrypt crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure crypto/dpaa2_sec: support AES-GMAC crypto/dpaa2_sec: increase ivsize range for AES-CTR crypto/dpaa2_sec: add missing ECN capability crypto/dpaa2_sec: add support for env variables dma/dpaa2: validate IOVA in pre-populate helpers dma/dpaa2: optimize context index ring enqueue drivers: add dpaa2 DMA bypass memory translation option net/dpaa2: set Tx confirmation on device init drivers: optimize dpaa2 Tx queue and channel mapping net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC net/dpaa2: enhance xstat implementation Hemant Agrawal (17): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types net/dpaa2: remove unused soft parser Tx code net/dpaa2: update MC dpni QoS and flow steering API net/dpaa2: rework flow engine net/dpaa2: support GENEVE flow item net/dpaa2: support flow meter and policer actions net/dpaa2: support flow table miss actions drivers: consume dpaa2 DQRR entries in batches drivers: resolve dpaa2 endpoint in the net driver drivers: align dpaa2 event port depths with hardware rings net/dpaa2: read MC version from device private data net/dpaa2: do not overwrite mbuf hash with drop priority bus/fslmc: reduce probe-time logging and MC traffic net/dpaa2: reject Rx queue deferred start Jun Yang (11): dma/dpaa2: fix array-bounds warning in dequeue path mempool/dpaa2: support ops index from primary in secondary net/dpaa2: remove unused soft parser driver drivers: refresh dpaa2 MC and SoC version info drivers: identify dpaa2 soft parser protocol drivers: assign dpaa2 Rx CGID per traffic class drivers: inherit dpaa2 rxq config for event queue net/dpaa2: rename Rx queue flags drivers: rework dpaa2 Tx confirmation net/dpaa2: ptp enhancements net/dpaa2: support Rx mempool per traffic class Prashant Gupta (1): bus/fslmc: defer bus initialization to probe doc/guides/rel_notes/release_26_11.rst | 6 + drivers/bus/fslmc/bus_fslmc_driver.h | 14 +- drivers/bus/fslmc/fslmc_bus.c | 177 +- drivers/bus/fslmc/fslmc_vfio.c | 196 +- drivers/bus/fslmc/fslmc_vfio.h | 30 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 83 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 7 - drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 45 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 7 +- drivers/bus/fslmc/private.h | 3 + .../fslmc/qbman/include/fsl_qbman_portal.h | 12 +- drivers/bus/fslmc/qbman/qbman_portal.c | 83 +- drivers/bus/fslmc/qbman/qbman_portal.h | 11 +- drivers/common/dpaax/rte_pmd_dpaax_qdma.h | 4 +- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 98 +- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 45 +- drivers/dma/dpaa2/dpaa2_qdma.c | 155 +- drivers/dma/dpaa2/dpaa2_qdma.h | 1 + drivers/event/dpaa2/dpaa2_eventdev.c | 76 +- drivers/event/dpaa2/dpaa2_eventdev.h | 4 +- drivers/mempool/dpaa2/dpaa2_hw_mempool.c | 88 +- drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 546 -- drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 2135 +++-- drivers/net/dpaa2/dpaa2_ethdev.h | 759 +- drivers/net/dpaa2/dpaa2_flow.c | 6966 ++++++++++------- drivers/net/dpaa2/dpaa2_meter.c | 588 ++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 - drivers/net/dpaa2/dpaa2_parser_decode.h | 1545 ++++ drivers/net/dpaa2/dpaa2_ptp.c | 161 +- drivers/net/dpaa2/dpaa2_recycle.c | 37 +- drivers/net/dpaa2/dpaa2_rxtx.c | 1902 ++--- drivers/net/dpaa2/dpaa2_sparser.c | 137 - drivers/net/dpaa2/dpaa2_sparser.h | 202 - drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 138 +- drivers/net/dpaa2/mc/fsl_dpni.h | 390 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 33 +- drivers/net/dpaa2/meson.build | 5 +- lib/cryptodev/rte_crypto_sym.h | 2 + lib/cryptodev/rte_cryptodev.c | 1 + 41 files changed, 10532 insertions(+), 6556 deletions(-) delete mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni.c create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v2 01/47] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 02/47] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure Prashant Gupta ` (46 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> In build_authenc_gcm_fd, when both AAD (auth_only_len > 0) and decrypt direction are active, the SGE layout occupies 8 entries plus 16 bytes of old_icv storage at index 8. The FLE pool buffer was only 256 bytes (8 x 32), causing old_icv to be written one entry past the end of the allocated buffer. The resulting virtual address was not mapped by the IOMMU, so DPAA2_VADDR_TO_IOVA returned 0 and the SEC engine received iova=0x00000000 as the ICV buffer address, triggering an SMMU translation fault (FSR=0x402 TF). Additionally, the upfront bpid/IVP initialization only covered sge+3, leaving sge+4 (the input data SGE when AAD is present) without a valid bpid or IVP assignment. Increase FLE_POOL_BUF_SIZE from 256 to 288 (9 x 32 bytes) to accommodate the full layout, and extend the bpid/IVP initialization to cover sge+4 in both branches of build_authenc_gcm_fd. Fixes: 13273250eec5 ("crypto/dpaa2_sec: support AES-GCM and CTR") Cc: stable@dpdk.org Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 38 ++++++++++++++++++++- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 2 +- drivers/dma/dpaa2/dpaa2_qdma.c | 12 +++++-- drivers/net/dpaa2/dpaa2_flow.c | 1 + 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 3d980d096f..96c2e56ff5 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -8,6 +8,9 @@ #include <time.h> #include <net/if.h> #include <unistd.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> #include <eal_export.h> #include <rte_ip.h> @@ -569,6 +572,7 @@ build_authenc_gcm_fd(dpaa2_sec_session *sess, DPAA2_SET_FLE_BPID(sge + 1, bpid); DPAA2_SET_FLE_BPID(sge + 2, bpid); DPAA2_SET_FLE_BPID(sge + 3, bpid); + DPAA2_SET_FLE_BPID(sge + 4, bpid); } else { DPAA2_SET_FD_IVP(fd); DPAA2_SET_FLE_IVP(fle); @@ -577,6 +581,7 @@ build_authenc_gcm_fd(dpaa2_sec_session *sess, DPAA2_SET_FLE_IVP((sge + 1)); DPAA2_SET_FLE_IVP((sge + 2)); DPAA2_SET_FLE_IVP((sge + 3)); + DPAA2_SET_FLE_IVP((sge + 4)); } /* Save the shared descriptor */ @@ -4332,17 +4337,48 @@ dpaa2_sec_uninit(const struct rte_cryptodev *dev) return 0; } +/* Parse a base-10 integer. Returns 0 on success and stores the result in + * *val, or a negative errno if the string is empty, malformed, or out of + * range. Unlike atoi() this detects errors instead of silently yielding 0. + */ +static int +dpaa2_sec_parse_int(const char *str, long *val) +{ + char *endptr; + long tmp; + + if (str == NULL || *str == '\0') + return -EINVAL; + + errno = 0; + tmp = strtol(str, &endptr, 10); + if (errno != 0) + return -errno; + if (endptr == str || *endptr != '\0') + return -EINVAL; + + *val = tmp; + + return 0; +} + static int check_devargs_handler(const char *key, const char *value, void *opaque) { struct rte_cryptodev *dev = (struct rte_cryptodev *)opaque; struct dpaa2_sec_dev_private *priv = dev->data->dev_private; + long val; if (!strcmp(key, "drv_strict_order")) { priv->en_loose_ordered = false; } else if (!strcmp(key, "drv_dump_mode")) { - dpaa2_sec_dp_dump = atoi(value); + if (dpaa2_sec_parse_int(value, &val)) { + DPAA2_SEC_WARN("Invalid %s value '%s', ignored", + key, value); + return -1; + } + dpaa2_sec_dp_dump = val; if (dpaa2_sec_dp_dump > DPAA2_SEC_DP_FULL_DUMP) { DPAA2_SEC_WARN("WARN: DPAA2_SEC_DP_DUMP_LEVEL is not " "supported, changing to FULL error" diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index 755c8e9cc3..ff32f3d860 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -17,7 +17,7 @@ extern uint8_t cryptodev_driver_id; /* FLE_POOL_NUM_BUFS is set as per the ipsec-secgw application */ #define FLE_POOL_NUM_BUFS 32000 -#define FLE_POOL_BUF_SIZE 256 +#define FLE_POOL_BUF_SIZE 288 #define FLE_POOL_CACHE_SIZE 512 #define FLE_SG_MEM_SIZE(num) (FLE_POOL_BUF_SIZE + ((num) * 32)) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index f7d94bb799..004dacf677 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -180,7 +180,7 @@ dpaa2_qdma_multi_eq(struct qdma_virt_queue *qdma_vq) return num_tx; } -static void +static int fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, struct dpaa2_qdma_rbp *rbp, uint64_t src, uint64_t dest, uint32_t fmt) @@ -256,6 +256,8 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, /* Final bit: 1, for last frame list */ DPAA2_SET_FLE_FIN(&fle[DPAA2_QDMA_DST_FLE]); + + return 0; } static void @@ -871,9 +873,15 @@ dpaa2_qdma_long_copy(struct qdma_virt_queue *qdma_vq, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - fle_sdd_pre_populate(fle_sdd, + ret = fle_sdd_pre_populate(fle_sdd, &qdma_vq->rbp, 0, 0, QBMAN_FLE_WORD4_FMT_SBF); + if (unlikely(ret)) { + if (!is_silent) + rte_mempool_put(qdma_vq->fle_pool, + fle_sdd); + return ret; + } } fle_post_populate(fle, src, dst, length); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..63c253ab3b 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -3,6 +3,7 @@ */ #include <sys/queue.h> +#include <rte_string_fns.h> #include <stdio.h> #include <errno.h> #include <stdint.h> -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 02/47] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 01/47] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 03/47] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta ` (45 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> When build_sec_fd fails at index loop inside the enqueue burst loops, the previously built FD entries (indices 0..loop-1) were never freed. The cleanup loop iterated in the wrong direction, starting at the failed index and going up to frames_to_send, which are entries that were never built. This caused silent FLE pool exhaustion, after which every subsequent build_sec_fd returned -ENOMEM, enqueue_burst returned 0 indefinitely, and the crypto-perf test hung. Fix both dpaa2_sec_enqueue_burst and dpaa2_sec_enqueue_burst_ordered by clamping frames_to_send to loop + 1 and iterating from 0 to free all allocated FLE buffers including the failed entry. Fixes: 623326dded3a ("crypto/dpaa2_sec: introduce poll mode driver") Cc: stable@dpdk.org Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 96c2e56ff5..e710b4fbd3 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1553,6 +1553,9 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, ret = build_sec_fd(*ops, &fd_arr[loop], bpid, dpaa2_qp); if (ret) { DPAA2_SEC_DP_DEBUG("FD build failed"); + frames_to_send = loop + 1; + for (loop = 0; loop < frames_to_send; loop++) + free_fle(&fd_arr[loop], dpaa2_qp); goto skip_tx; } ops++; @@ -1912,6 +1915,9 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, ret = build_sec_fd(*ops, &fd_arr[loop], bpid, dpaa2_qp); if (ret) { DPAA2_SEC_DP_DEBUG("FD build failed"); + frames_to_send = loop + 1; + for (loop = 0; loop < frames_to_send; loop++) + free_fle(&fd_arr[loop], dpaa2_qp); goto skip_tx; } ops++; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 03/47] crypto/dpaa2_sec: support AES-GMAC 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 01/47] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 02/47] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-24 10:32 ` [EXTERNAL] " Akhil Goyal 2026-09-10 13:51 ` [PATCH v2 04/47] crypto/dpaa2_sec: increase ivsize range for AES-CTR Prashant Gupta ` (44 subsequent siblings) 47 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Akhil Goyal, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add AES-GMAC as a supported AEAD algorithm for IPsec protocol offload. AES-GMAC provides NULL encryption with GMAC authentication and maps to OP_PCL_IPSEC_AES_NULL_WITH_GMAC in the SEC protocol control word. When AES_GMAC is specified as an AUTH (non-AEAD) algorithm, return -ENOTSUP with an informative message directing the user to the AEAD path. Add RTE_CRYPTO_AEAD_AES_GMAC to the AEAD algorithm enum and expose the capability in dpaa2_sec_capabilities. Signed-off-by: Akhil Goyal <gakhil@marvell.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 6 ++++ drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 14 ++++++++- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 33 ++++++++++++++++++++- lib/cryptodev/rte_crypto_sym.h | 2 ++ lib/cryptodev/rte_cryptodev.c | 1 + 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 87c7e81bde..2eb5c4fe56 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -55,6 +55,12 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Added AES-GMAC AEAD algorithm.** + + Added ``RTE_CRYPTO_AEAD_AES_GMAC`` to the AEAD algorithm enumeration, for + NULL encryption with GMAC authentication. The NXP dpaa2_sec PMD supports it + for IPsec protocol offload. + Removed Items ------------- diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index e710b4fbd3..16af02e758 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ @@ -2978,6 +2978,13 @@ dpaa2_sec_ipsec_aead_init(struct rte_crypto_aead_xform *aead_xform, aeaddata->algmode = OP_ALG_AAI_CCM; session->aead_alg = RTE_CRYPTO_AEAD_AES_CCM; break; + case RTE_CRYPTO_AEAD_AES_GMAC: + /** + * AES-GMAC is an AEAD algo with NULL encryption and GMAC + * authentication. + */ + aeaddata->algtype = OP_PCL_IPSEC_AES_NULL_WITH_GMAC; + break; default: DPAA2_SEC_ERR("Crypto: Undefined AEAD specified %u", aead_xform->algo); @@ -3049,6 +3056,9 @@ dpaa2_sec_ipsec_proto_init(struct rte_crypto_cipher_xform *cipher_xform, authdata->algtype = OP_PCL_IPSEC_HMAC_MD5_96; authdata->algmode = OP_ALG_AAI_HMAC; break; + case RTE_CRYPTO_AUTH_AES_GMAC: + DPAA2_SEC_ERR("AES_GMAC is supported as AEAD algo for IPSEC proto only"); + return -ENOTSUP; case RTE_CRYPTO_AUTH_SHA224_HMAC: authdata->algmode = OP_ALG_AAI_HMAC; if (session->digest_length == 6) @@ -3220,6 +3230,7 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev, case OP_PCL_IPSEC_AES_GCM8: case OP_PCL_IPSEC_AES_GCM12: case OP_PCL_IPSEC_AES_GCM16: + case OP_PCL_IPSEC_AES_NULL_WITH_GMAC: memcpy(encap_pdb.gcm.salt, (uint8_t *)&(ipsec_xform->salt), 4); break; @@ -3360,6 +3371,7 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev, case OP_PCL_IPSEC_AES_GCM8: case OP_PCL_IPSEC_AES_GCM12: case OP_PCL_IPSEC_AES_GCM16: + case OP_PCL_IPSEC_AES_NULL_WITH_GMAC: memcpy(decap_pdb.gcm.salt, (uint8_t *)&(ipsec_xform->salt), 4); break; diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index ff32f3d860..1824cc4a60 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2020-2024 NXP + * Copyright 2016,2020-2026 NXP * */ @@ -762,6 +762,37 @@ static const struct rte_cryptodev_capabilities dpaa2_sec_capabilities[] = { }, } }, } }, + { /* AES GMAC (AEAD) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD, + {.aead = { + .algo = RTE_CRYPTO_AEAD_AES_GMAC, + .block_size = 16, + .key_size = { + .min = 16, + .max = 32, + .increment = 8 + }, + .digest_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .aad_size = { + .min = 0, + .max = 65535, + .increment = 1 + }, + .iv_size = { + .min = 12, + .max = 16, + .increment = 4 + } + }, } + }, } + }, + RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() }; diff --git a/lib/cryptodev/rte_crypto_sym.h b/lib/cryptodev/rte_crypto_sym.h index 630fd153bd..f65db616a0 100644 --- a/lib/cryptodev/rte_crypto_sym.h +++ b/lib/cryptodev/rte_crypto_sym.h @@ -508,6 +508,8 @@ enum rte_crypto_aead_algorithm { /**< AES algorithm in NCA5 mode */ RTE_CRYPTO_AEAD_ZUC_NCA6, /**< ZUC-256 algorithm in NCA6 mode */ + RTE_CRYPTO_AEAD_AES_GMAC, + /**< AES algorithm in GMAC mode. */ }; /** Symmetric AEAD Operations */ diff --git a/lib/cryptodev/rte_cryptodev.c b/lib/cryptodev/rte_cryptodev.c index 829a5d0846..fa78cd1f1f 100644 --- a/lib/cryptodev/rte_cryptodev.c +++ b/lib/cryptodev/rte_cryptodev.c @@ -186,6 +186,7 @@ crypto_aead_algorithm_strings[] = { [RTE_CRYPTO_AEAD_SNOW5G_NCA4] = "snow5g-nca4", [RTE_CRYPTO_AEAD_AES_NCA5] = "aes-nca5", [RTE_CRYPTO_AEAD_ZUC_NCA6] = "zuc-nca6", + [RTE_CRYPTO_AEAD_AES_GMAC] = "aes-gmac", }; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* RE: [EXTERNAL] [PATCH v2 03/47] crypto/dpaa2_sec: support AES-GMAC 2026-09-10 13:51 ` [PATCH v2 03/47] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta @ 2026-09-24 10:32 ` Akhil Goyal 0 siblings, 0 replies; 356+ messages in thread From: Akhil Goyal @ 2026-09-24 10:32 UTC (permalink / raw) To: Prashant Gupta, stephen@networkplumber.org, dev@dpdk.org; +Cc: Gagandeep Singh > From: Gagandeep Singh <g.singh@nxp.com> > > Add AES-GMAC as a supported AEAD algorithm for IPsec protocol > offload. AES-GMAC provides NULL encryption with GMAC authentication > and maps to OP_PCL_IPSEC_AES_NULL_WITH_GMAC in the SEC protocol > control word. > > When AES_GMAC is specified as an AUTH (non-AEAD) algorithm, return > -ENOTSUP with an informative message directing the user to the AEAD > path. > > Add RTE_CRYPTO_AEAD_AES_GMAC to the AEAD algorithm enum and expose > the capability in dpaa2_sec_capabilities. > > Signed-off-by: Akhil Goyal <gakhil@marvell.com> > Signed-off-by: Gagandeep Singh <g.singh@nxp.com> AES-GMAC is considered as an auth algorithm, we need not make it as AEAD. This was discussed earlier also and the idea of moving to AEAD was dropped. These crypto patches should be coming as a separate series for crypto tree. It seems these patches are resubmitted for https://patchwork.dpdk.org/project/dpdk/list/?series=38909 Better submit crypto patches separately. Please remove my sign-off from this patch and consider supporting GMAC as auth algo. Furthermore, the lib and PMD changes should be separate patch. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v2 04/47] crypto/dpaa2_sec: increase ivsize range for AES-CTR 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (2 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 03/47] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 05/47] crypto/dpaa2_sec: add missing ECN capability Prashant Gupta ` (43 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Widen the AES-CTR IV size range from the fixed 16-byte value to [12, 16] with a 4-byte increment. This allows 96-bit IVs (the standard NIST SP 800-38A recommendation) in addition to 128-bit IVs, aligning with common usage and test-vector expectations. The change applies to both dpaa2_sec_capabilities and dpaa2_pdcp_capabilities. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index 1824cc4a60..7e18e83858 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -625,9 +625,9 @@ static const struct rte_cryptodev_capabilities dpaa2_sec_capabilities[] = { .increment = 8 }, .iv_size = { - .min = 16, + .min = 12, .max = 16, - .increment = 0 + .increment = 4 }, }, } }, } @@ -855,9 +855,9 @@ static const struct rte_cryptodev_capabilities dpaa2_pdcp_capabilities[] = { .increment = 8 }, .iv_size = { - .min = 16, + .min = 12, .max = 16, - .increment = 0 + .increment = 4 } }, } }, } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 05/47] crypto/dpaa2_sec: add missing ECN capability 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (3 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 04/47] crypto/dpaa2_sec: increase ivsize range for AES-CTR Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 06/47] crypto/dpaa2_sec: add support for env variables Prashant Gupta ` (42 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Set the .ecn = 1 flag in both tunnel-mode security capability entries to advertise that the driver supports ECN (Explicit Congestion Notification) copying during IPsec encap/decap. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index 7e18e83858..16b8273a79 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -1004,6 +1004,7 @@ static const struct rte_security_capability dpaa2_sec_security_cap[] = { .copy_df = 1, .copy_dscp = 1, .dec_ttl = 1, + .ecn = 1, .esn = 1, }, .replay_win_sz_max = 1024 @@ -1023,6 +1024,7 @@ static const struct rte_security_capability dpaa2_sec_security_cap[] = { .copy_df = 1, .copy_dscp = 1, .dec_ttl = 1, + .ecn = 1, .esn = 1, }, .replay_win_sz_max = 1024 -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 06/47] crypto/dpaa2_sec: add support for env variables 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (4 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 05/47] crypto/dpaa2_sec: add missing ECN capability Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-24 10:33 ` [EXTERNAL] " Akhil Goyal 2026-09-10 13:51 ` [PATCH v2 07/47] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (41 subsequent siblings) 47 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Allow driver configuration via environment variables as a fallback when devargs are not provided. After processing devargs (or when devargs are absent), check DRIVER_STRICT_ORDER and DRIVER_DUMP_MODE environment variables to set en_loose_ordered and dpaa2_sec_dp_dump. This lets users configure the driver without modifying EAL arguments, useful in environments where command-line access is restricted. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 40 ++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 16af02e758..1416c8dc67 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -4412,25 +4412,57 @@ check_devargs_handler(const char *key, const char *value, static void dpaa2_sec_get_devargs(struct rte_cryptodev *cryptodev, const char *key) { + struct dpaa2_sec_dev_private *internals; struct rte_kvargs *kvlist; struct rte_devargs *devargs; + int ret; + char *env; + long val; + + internals = cryptodev->data->dev_private; devargs = cryptodev->device->devargs; if (!devargs) - return; + goto env_set; kvlist = rte_kvargs_parse(devargs->args, NULL); if (!kvlist) - return; + goto env_set; if (!rte_kvargs_count(kvlist, key)) { rte_kvargs_free(kvlist); - return; + goto env_set; } - rte_kvargs_process(kvlist, key, + ret = rte_kvargs_process(kvlist, key, check_devargs_handler, (void *)cryptodev); rte_kvargs_free(kvlist); + if (!ret) + return; + +env_set: + env = getenv(DRIVER_STRICT_ORDER); + if (env) { + if (dpaa2_sec_parse_int(env, &val)) + DPAA2_SEC_WARN("Invalid %s value '%s', ignored", + DRIVER_STRICT_ORDER, env); + else + internals->en_loose_ordered = !val; + } + + env = getenv(DRIVER_DUMP_MODE); + if (env) { + if (dpaa2_sec_parse_int(env, &val)) { + DPAA2_SEC_WARN("Invalid %s value '%s', ignored", + DRIVER_DUMP_MODE, env); + } else { + if (val > DPAA2_SEC_DP_FULL_DUMP) + val = DPAA2_SEC_DP_FULL_DUMP; + else if (val < DPAA2_SEC_DP_NO_DUMP) + val = DPAA2_SEC_DP_NO_DUMP; + dpaa2_sec_dp_dump = val; + } + } } static int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* RE: [EXTERNAL] [PATCH v2 06/47] crypto/dpaa2_sec: add support for env variables 2026-09-10 13:51 ` [PATCH v2 06/47] crypto/dpaa2_sec: add support for env variables Prashant Gupta @ 2026-09-24 10:33 ` Akhil Goyal 0 siblings, 0 replies; 356+ messages in thread From: Akhil Goyal @ 2026-09-24 10:33 UTC (permalink / raw) To: Prashant Gupta, stephen@networkplumber.org, dev@dpdk.org; +Cc: Gagandeep Singh > From: Gagandeep Singh <g.singh@nxp.com> > > Allow driver configuration via environment variables as a fallback > when devargs are not provided. After processing devargs (or when > devargs are absent), check DRIVER_STRICT_ORDER and DRIVER_DUMP_MODE > environment variables to set en_loose_ordered and dpaa2_sec_dp_dump. > > This lets users configure the driver without modifying EAL arguments, > useful in environments where command-line access is restricted. > > Signed-off-by: Gagandeep Singh <g.singh@nxp.com> > --- These devargs without proper documentation cannot be accepted. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v2 07/47] net/dpaa2: fix integer overflow in CCSR region mapping 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (5 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 06/47] crypto/dpaa2_sec: add support for env variables Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 08/47] dma/dpaa2: fix array-bounds warning in dequeue path Prashant Gupta ` (40 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is defined as sysconf(_SC_PAGESIZE) which may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). Use sysconf() explicitly with a signed long, check for errors, and compute map_len separately with unsigned arithmetic before passing to mmap. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..80c20272ce 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,8 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +185,27 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } start = addr & PAGE_MASK; offset = addr - start; len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + map_len = len & ~(page_size - 1); + if (map_len < (size_t)page_size) + map_len = (size_t)page_size; + + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 08/47] dma/dpaa2: fix array-bounds warning in dequeue path 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (6 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 07/47] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 09/47] bus/fslmc: defer bus initialization to probe Prashant Gupta ` (39 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Jun Yang From: Jun Yang <jun.yang@nxp.com> In dpaa2_qdma_dq_fd, passing a local uint16_t variable directly as a pointer to qdma_cntx_idx_ring_eq caused a compiler array-bounds warning because the function takes a pointer to an element of the ring array. Add a per-queue scratch buffer idxs[DPAA2_QDMA_MAX_DESC] to struct qdma_virt_queue and use idxs[0] instead of a local variable pointer. Also consolidate the fle_sdd pointer assignment for LONG and SG FD types to avoid code duplication. Fixes: 388e888dc082 ("dma/dpaa2: support short FD") Cc: stable@dpdk.org Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/dma/dpaa2/dpaa2_qdma.c | 24 ++++++++---------------- drivers/dma/dpaa2/dpaa2_qdma.h | 1 + 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 004dacf677..6fd3530f0d 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -943,35 +943,27 @@ dpaa2_qdma_dq_fd(const struct qbman_fd *fd, enum dpaa2_qdma_fd_type type; int ret; struct qdma_cntx_sg *cntx_sg; - struct qdma_cntx_fle_sdd *fle_sdd; + struct qdma_cntx_fle_sdd *fle_sdd = NULL; att = dpaa2_qdma_fd_get_att(fd); type = DPAA2_QDMA_FD_ATT_TYPE(att); - if (type == DPAA2_QDMA_FD_SHORT) { - idx = DPAA2_QDMA_FD_ATT_CNTX(att); - ret = qdma_cntx_idx_ring_eq(qdma_vq->ring_cntx_idx, - &idx, 1, free_space); - if (unlikely(ret != 1)) - return -ENOSPC; - - return 0; - } - if (type == DPAA2_QDMA_FD_LONG) { - idx = DPAA2_QDMA_FD_ATT_CNTX(att); + if (type == DPAA2_QDMA_FD_LONG || type == DPAA2_QDMA_FD_SG) { fle_sdd = (void *)(uintptr_t)DPAA2_GET_FD_FLC(fd); qdma_vq->fle_elem[*fle_elem_nb] = fle_sdd; (*fle_elem_nb)++; + } + if (type == DPAA2_QDMA_FD_SHORT || + type == DPAA2_QDMA_FD_LONG) { + idx = DPAA2_QDMA_FD_ATT_CNTX(att); + qdma_vq->idxs[0] = idx; ret = qdma_cntx_idx_ring_eq(qdma_vq->ring_cntx_idx, - &idx, 1, free_space); + qdma_vq->idxs, 1, free_space); if (unlikely(ret != 1)) return -ENOSPC; return 0; } if (type == DPAA2_QDMA_FD_SG) { - fle_sdd = (void *)(uintptr_t)DPAA2_GET_FD_FLC(fd); - qdma_vq->fle_elem[*fle_elem_nb] = fle_sdd; - (*fle_elem_nb)++; cntx_sg = container_of(fle_sdd, struct qdma_cntx_sg, fle_sdd); ret = qdma_cntx_idx_ring_eq(qdma_vq->ring_cntx_idx, diff --git a/drivers/dma/dpaa2/dpaa2_qdma.h b/drivers/dma/dpaa2/dpaa2_qdma.h index e2d2eb4fa8..98c64f7b45 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.h +++ b/drivers/dma/dpaa2/dpaa2_qdma.h @@ -290,6 +290,7 @@ struct qdma_virt_queue { struct qdma_cntx_idx_ring *ring_cntx_idx; /**Used for silent enabled*/ + uint16_t idxs[DPAA2_QDMA_MAX_DESC]; struct qdma_cntx_sg *cntx_sg[DPAA2_QDMA_MAX_DESC]; struct qdma_cntx_fle_sdd *cntx_fle_sdd[DPAA2_QDMA_MAX_DESC]; uint16_t silent_idx; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 09/47] bus/fslmc: defer bus initialization to probe 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (7 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 08/47] dma/dpaa2: fix array-bounds warning in dequeue path Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 10/47] dma/dpaa2: validate IOVA in pre-populate helpers Prashant Gupta ` (38 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev The fslmc bus initialization (register the sequence number mbuf dynfield, set up the VFIO group, DMA map the memory segments) needs the DPDK heap and the memory segment list in shared (hugepage) memory for multi-process sharing. But these are not available during the bus scan (EAL runs rte_bus_scan() before memzone, memory and malloc heap init), so it fails there. Device discovery does not need it, and get_iommu_class() only checks sysfs paths to report the IOVA mode, so the init is not needed in scan. Move it back to probe. Fixes: cdefd2e980bd ("drivers/bus: initialize NXP bus specifics in scan") Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- drivers/bus/fslmc/fslmc_bus.c | 92 +++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index 3626b12316..ee162b0ed8 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -368,46 +368,6 @@ rte_fslmc_scan(void) /* If debugging is enabled, device list is dumped to log output */ dump_device_list(); - /* Bus initialization - only if devices were found */ - if (!TAILQ_EMPTY(&rte_fslmc_bus.device_list)) { - static const struct rte_mbuf_dynfield dpaa2_seqn_dynfield_desc = { - .name = DPAA2_SEQN_DYNFIELD_NAME, - .size = sizeof(dpaa2_seqn_t), - .align = alignof(dpaa2_seqn_t), - }; - - dpaa2_seqn_dynfield_offset = - rte_mbuf_dynfield_register(&dpaa2_seqn_dynfield_desc); - if (dpaa2_seqn_dynfield_offset < 0) { - DPAA2_BUS_ERR("Failed to register mbuf field for dpaa sequence number"); - return 0; - } - - ret = fslmc_vfio_setup_group(); - if (ret) { - DPAA2_BUS_ERR("Unable to setup VFIO %d", ret); - return 0; - } - - /* Map existing segments as well as, in case of hotpluggable memory, - * install callback handler. - */ - if (rte_eal_process_type() == RTE_PROC_PRIMARY) { - ret = fslmc_vfio_dmamap(); - if (ret) { - DPAA2_BUS_ERR("Unable to DMA map existing VAs: (%d)", ret); - DPAA2_BUS_ERR("FSLMC VFIO Mapping failed"); - return 0; - } - } - - ret = fslmc_vfio_process_group(); - if (ret) { - DPAA2_BUS_ERR("Unable to setup devices %d", ret); - return 0; - } - } - process_once = 1; return 0; @@ -423,6 +383,56 @@ rte_fslmc_scan(void) return 0; } +/* Bus initialization needs the DPDK heap and DMA mapping of the memory + * segments, which EAL only sets up after the bus scan, so it is done here. + */ +static int +rte_fslmc_probe(struct rte_bus *bus) +{ + static const struct rte_mbuf_dynfield dpaa2_seqn_dynfield_desc = { + .name = DPAA2_SEQN_DYNFIELD_NAME, + .size = sizeof(dpaa2_seqn_t), + .align = alignof(dpaa2_seqn_t), + }; + int ret; + + if (TAILQ_EMPTY(&rte_fslmc_bus.device_list)) + return 0; + + dpaa2_seqn_dynfield_offset = + rte_mbuf_dynfield_register(&dpaa2_seqn_dynfield_desc); + if (dpaa2_seqn_dynfield_offset < 0) { + DPAA2_BUS_ERR("Failed to register mbuf field for dpaa sequence number"); + return 0; + } + + ret = fslmc_vfio_setup_group(); + if (ret) { + DPAA2_BUS_ERR("Unable to setup VFIO %d", ret); + return 0; + } + + /* Map existing segments as well as, in case of hotpluggable memory, + * install callback handler. + */ + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + ret = fslmc_vfio_dmamap(); + if (ret) { + DPAA2_BUS_ERR("Unable to DMA map existing VAs: (%d)", ret); + DPAA2_BUS_ERR("FSLMC VFIO Mapping failed"); + return 0; + } + } + + ret = fslmc_vfio_process_group(); + if (ret) { + DPAA2_BUS_ERR("Unable to setup devices %d", ret); + return 0; + } + + return rte_bus_generic_probe(bus); +} + static bool fslmc_bus_match(const struct rte_driver *drv, const struct rte_device *dev) { @@ -544,7 +554,7 @@ fslmc_bus_unplug_device(struct rte_device *rte_dev) struct rte_bus rte_fslmc_bus = { .scan = rte_fslmc_scan, - .probe = rte_bus_generic_probe, + .probe = rte_fslmc_probe, .cleanup = rte_fslmc_close, .parse = rte_fslmc_parse, .dev_compare = fslmc_dev_compare, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 10/47] dma/dpaa2: validate IOVA in pre-populate helpers 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (8 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 09/47] bus/fslmc: defer bus initialization to probe Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 11/47] dma/dpaa2: optimize context index ring enqueue Prashant Gupta ` (37 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> fle_sdd_pre_populate() and fle_sdd_sg_pre_populate() converted the SDD and SG entry virtual addresses to IOVA with DPAA2_VADDR_TO_IOVA(), which does not verify that the range is actually mapped in the IOMMU/SMMU. An unmapped buffer was silently programmed into the hardware descriptor, leading to an SMMU translation fault at transfer time that is hard to trace back to the missing mapping. Use DPAA2_VADDR_TO_IOVA_AND_CHECK() for the SDD, source SG and destination SG buffers and rte_panic() with the offending address and size when the translation is missing, so the misconfiguration is caught early and clearly. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/dma/dpaa2/dpaa2_qdma.c | 42 ++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 6fd3530f0d..8a180ab400 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -187,7 +187,15 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, { struct qbman_fle *fle = fle_sdd->fle; struct qdma_sdd *sdd = fle_sdd->sdd; - uint64_t sdd_iova = DPAA2_VADDR_TO_IOVA(sdd); + uint64_t sdd_iova, iova_size; + + iova_size = sizeof(struct qdma_sdd) * DPAA2_QDMA_MAX_SDD; + sdd_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(sdd, iova_size); + if (sdd_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for sdd(%p)(size=%" PRIu64 ")", + sdd, iova_size); + return -ENOMEM; + } /* first frame list to source descriptor */ DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_SDD_FLE], sdd_iova); @@ -285,22 +293,36 @@ sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) } } -static void +static int fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, struct qdma_virt_queue *qdma_vq) { struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; struct qdma_sg_entry *dst_sge = sg_cntx->sg_dst_entry; - rte_iova_t src_sge_iova, dst_sge_iova; + rte_iova_t src_sge_iova, dst_sge_iova, iova_size; struct dpaa2_qdma_rbp *rbp = &qdma_vq->rbp; memset(sg_cntx, 0, sizeof(struct qdma_cntx_sg)); - src_sge_iova = DPAA2_VADDR_TO_IOVA(src_sge); - dst_sge_iova = DPAA2_VADDR_TO_IOVA(dst_sge); + iova_size = RTE_DPAAX_QDMA_JOB_SUBMIT_MAX * + sizeof(struct qdma_sg_entry); + + src_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(src_sge, iova_size); + if (src_sge_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for src_sge(%p)(size=%" PRIu64 ")", + src_sge, (uint64_t)iova_size); + return -ENOMEM; + } + + dst_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(dst_sge, iova_size); + if (dst_sge_iova == RTE_BAD_IOVA) { + DPAA2_QDMA_ERR("No IOMMU map for dst_sge(%p)(size=%" PRIu64 ")", + dst_sge, (uint64_t)iova_size); + return -ENOMEM; + } sg_entry_pre_populate(sg_cntx); - fle_sdd_pre_populate(&sg_cntx->fle_sdd, + return fle_sdd_pre_populate(&sg_cntx->fle_sdd, rbp, src_sge_iova, dst_sge_iova, QBMAN_FLE_WORD4_FMT_SGE); } @@ -671,7 +693,13 @@ dpaa2_qdma_copy_sg(void *dev_private, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + if (unlikely(ret)) { + if (!qdma_dev->is_silent) + rte_mempool_put(qdma_vq->fle_pool, + cntx_sg); + return ret; + } if (!qdma_dev->is_silent && cntx_sg && idx_addr) { for (i = 0; i < nb_src; i++) cntx_sg->cntx_idx[i] = idx_addr[i]; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 11/47] dma/dpaa2: optimize context index ring enqueue 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (9 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 10/47] dma/dpaa2: validate IOVA in pre-populate helpers Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 12/47] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta ` (36 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> qdma_cntx_idx_ring_eq() copied the context indices into the ring one element at a time in a loop, updating the tail on every iteration. Replace the per-element loop with rte_memcpy(), handling the ring wrap-around as at most two contiguous copies, and update the tail once. This reduces the per-burst overhead on the dequeue completion path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/dma/dpaa2/dpaa2_qdma.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 8a180ab400..277be37b41 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -66,15 +66,23 @@ qdma_cntx_idx_ring_eq(struct qdma_cntx_idx_ring *ring, const uint16_t *elem, uint16_t nb, uint16_t *free_space) { - uint16_t i; - if (unlikely(nb > ring->free_space)) return 0; - for (i = 0; i < nb; i++) { - ring->cntx_idx_ring[ring->tail] = elem[i]; - ring->tail = (ring->tail + 1) & - (DPAA2_QDMA_MAX_DESC - 1); + if ((ring->tail + nb) < DPAA2_QDMA_MAX_DESC) { + rte_memcpy(&ring->cntx_idx_ring[ring->tail], + elem, nb * sizeof(uint16_t)); + ring->tail += nb; + } else { + rte_memcpy(&ring->cntx_idx_ring[ring->tail], + elem, + (DPAA2_QDMA_MAX_DESC - ring->tail) * + sizeof(uint16_t)); + rte_memcpy(&ring->cntx_idx_ring[0], + &elem[DPAA2_QDMA_MAX_DESC - ring->tail], + (nb - DPAA2_QDMA_MAX_DESC + ring->tail) * + sizeof(uint16_t)); + ring->tail = (ring->tail + nb) & (DPAA2_QDMA_MAX_DESC - 1); } ring->free_space -= nb; ring->nb_in_ring += nb; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 12/47] drivers: add dpaa2 DMA bypass memory translation option 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (10 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 11/47] dma/dpaa2: optimize context index ring enqueue Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 13/47] mempool/dpaa2: support ops index from primary in secondary Prashant Gupta ` (35 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add RTE_DPAAX_QDMA_BMT_FLAG flag to allow callers to bypass memory translation (BMT) for DMA operations. This is needed for some PCIe scenarios where IOMMU translation should be skipped. The flag is propagated to all SG entry and FD populate helpers via a new 'bmt' parameter, defaulting to DISABLE when the flag is not set. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/common/dpaax/rte_pmd_dpaax_qdma.h | 4 +- drivers/dma/dpaa2/dpaa2_qdma.c | 59 ++++++++++------------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/drivers/common/dpaax/rte_pmd_dpaax_qdma.h b/drivers/common/dpaax/rte_pmd_dpaax_qdma.h index 8f2fc83f8d..6bd72b0b0e 100644 --- a/drivers/common/dpaax/rte_pmd_dpaax_qdma.h +++ b/drivers/common/dpaax/rte_pmd_dpaax_qdma.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2021-2024 NXP + * Copyright 2021-2024, 2026 NXP */ #ifndef RTE_PMD_DPAAX_QDMA_H @@ -7,6 +7,8 @@ #include <rte_compat.h> +#define RTE_DPAAX_QDMA_BMT_FLAG RTE_BIT64(7) + #define RTE_DPAAX_QDMA_COPY_IDX_OFFSET 8 #define RTE_DPAAX_QDMA_SG_IDX_ADDR_ALIGN \ RTE_BIT64(RTE_DPAAX_QDMA_COPY_IDX_OFFSET) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 277be37b41..f9ffda6740 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -277,7 +277,7 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, } static void -sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) +sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx, int bmt) { uint16_t i; struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; @@ -287,23 +287,17 @@ sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) /* source SG */ src_sge[i].ctrl.sl = QDMA_SG_SL_LONG; src_sge[i].ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - src_sge[i].ctrl.bmt = QDMA_SG_BMT_DISABLE; + src_sge[i].ctrl.bmt = bmt; /* destination SG */ dst_sge[i].ctrl.sl = QDMA_SG_SL_LONG; dst_sge[i].ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - dst_sge[i].ctrl.bmt = QDMA_SG_BMT_DISABLE; + dst_sge[i].ctrl.bmt = bmt; } } static int fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, - struct qdma_virt_queue *qdma_vq) + struct qdma_virt_queue *qdma_vq, int bmt) { struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; struct qdma_sg_entry *dst_sge = sg_cntx->sg_dst_entry; @@ -329,7 +323,7 @@ fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, return -ENOMEM; } - sg_entry_pre_populate(sg_cntx); + sg_entry_pre_populate(sg_cntx, bmt); return fle_sdd_pre_populate(&sg_cntx->fle_sdd, rbp, src_sge_iova, dst_sge_iova, QBMAN_FLE_WORD4_FMT_SGE); @@ -394,7 +388,7 @@ sg_fle_post_populate(struct qbman_fle fle[], static inline uint32_t sg_entry_populate(const struct rte_dma_sge *src, const struct rte_dma_sge *dst, struct qdma_cntx_sg *sg_cntx, - uint16_t nb_sge) + uint16_t nb_sge, int bmt) { uint16_t i; uint32_t total_len = 0; @@ -410,19 +404,13 @@ sg_entry_populate(const struct rte_dma_sge *src, src_sge->data_len.data_len_sl0 = src[i].length; src_sge->ctrl.sl = QDMA_SG_SL_LONG; src_sge->ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - src_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE; + src_sge->ctrl.bmt = bmt; dst_sge->addr_lo = (uint32_t)dst[i].addr; dst_sge->addr_hi = (dst[i].addr >> 32); dst_sge->data_len.data_len_sl0 = dst[i].length; dst_sge->ctrl.sl = QDMA_SG_SL_LONG; dst_sge->ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - dst_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE; + dst_sge->ctrl.bmt = bmt; total_len += src[i].length; if (i == (nb_sge - 1)) { @@ -701,7 +689,9 @@ dpaa2_qdma_copy_sg(void *dev_private, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); if (unlikely(ret)) { if (!qdma_dev->is_silent) rte_mempool_put(qdma_vq->fle_pool, @@ -726,7 +716,9 @@ dpaa2_qdma_copy_sg(void *dev_private, offsetof(struct qdma_cntx_sg, sg_src_entry); dst_sge_iova = cntx_iova + offsetof(struct qdma_cntx_sg, sg_dst_entry); - len = sg_entry_populate(src, dst, cntx_sg, nb_src); + len = sg_entry_populate(src, dst, cntx_sg, nb_src, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); fle_populate(fle, sdd, sdd_iova, &qdma_vq->rbp, src_sge_iova, dst_sge_iova, len, @@ -759,14 +751,14 @@ dpaa2_qdma_copy_sg(void *dev_private, static inline void qdma_populate_fd_pci(uint64_t src, uint64_t dest, uint32_t len, struct qbman_fd *fd, - struct dpaa2_qdma_rbp *rbp, int ser) + struct dpaa2_qdma_rbp *rbp, int ser, int bmt) { fd->simple_pci.saddr_lo = lower_32_bits(src); fd->simple_pci.saddr_hi = upper_32_bits(src); fd->simple_pci.len_sl = len; - fd->simple_pci.bmt = DPAA2_QDMA_BMT_DISABLE; + fd->simple_pci.bmt = bmt; fd->simple_pci.fmt = DPAA2_QDMA_FD_SHORT_FORMAT; fd->simple_pci.sl = 1; fd->simple_pci.ser = ser; @@ -802,14 +794,14 @@ qdma_populate_fd_pci(uint64_t src, uint64_t dest, static inline void qdma_populate_fd_ddr(uint64_t src, uint64_t dest, - uint32_t len, struct qbman_fd *fd, int ser) + uint32_t len, struct qbman_fd *fd, int ser, int bmt) { fd->simple_ddr.saddr_lo = lower_32_bits(src); fd->simple_ddr.saddr_hi = upper_32_bits(src); fd->simple_ddr.len = len; - fd->simple_ddr.bmt = DPAA2_QDMA_BMT_DISABLE; + fd->simple_ddr.bmt = bmt; fd->simple_ddr.fmt = DPAA2_QDMA_FD_SHORT_FORMAT; fd->simple_ddr.sl = 1; fd->simple_ddr.ser = ser; @@ -847,15 +839,16 @@ dpaa2_qdma_short_copy(struct qdma_virt_queue *qdma_vq, if (qdma_vq->rbp.drbp || qdma_vq->rbp.srbp) { /** PCIe EP*/ - qdma_populate_fd_pci(src, - dst, length, - fd, &qdma_vq->rbp, - is_silent ? 0 : 1); + qdma_populate_fd_pci(src, dst, length, + fd, &qdma_vq->rbp, is_silent ? 0 : 1, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } else { /** DDR or PCIe RC*/ - qdma_populate_fd_ddr(src, - dst, length, - fd, is_silent ? 0 : 1); + qdma_populate_fd_ddr(src, dst, length, + fd, is_silent ? 0 : 1, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } dpaa2_qdma_fd_save_att(fd, DPAA2_QDMA_IDX_FROM_FLAG(flags), DPAA2_QDMA_FD_SHORT); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 13/47] mempool/dpaa2: support ops index from primary in secondary 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (11 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 12/47] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 14/47] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (34 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Hemant Agrawal From: Jun Yang <jun.yang@nxp.com> Secondary processes call rte_dpaa2_mpool_get_ops_idx() but the ops index is registered only in the primary process. The secondary had no way to learn the index, causing it to use the initial sentinel value RTE_MEMPOOL_MAX_OPS_IDX and return an error. Register an IPC action handler in the primary during pool creation. Secondary processes send DPAA2_POOL_OPS_IDX_REQ over the dpaa2_pool_mp_sync channel and receive the ops index back. Also handle the case where rte_mp_action_register returns ENOTSUP (e.g. no secondary process support enabled at build time) by treating it as non-fatal, and improve the error message in rte_hw_mbuf_free_pool to include the pool name. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/mempool/dpaa2/dpaa2_hw_mempool.c | 88 +++++++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c index ee001d8ce0..f19b6c039a 100644 --- a/drivers/mempool/dpaa2/dpaa2_hw_mempool.c +++ b/drivers/mempool/dpaa2/dpaa2_hw_mempool.c @@ -34,16 +34,90 @@ #include <dpaax_iova_table.h> +#define DPAA2_POOL_MP_SYNC "dpaa2_pool_mp_sync" +#define DPAA2_POOL_OPS_IDX_REQ 0x100 +#define DPAA2_POOL_OPS_IDX_RSP 0x101 + +static int s_dpaa2_pool_mp_msg_setup; + +struct dpaa2_pool_mp_msg { + uint16_t msg_type; + uint8_t msg_data[]; +}; + RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_bpid_info) struct dpaa2_bp_info *rte_dpaa2_bpid_info; static struct dpaa2_bp_list *h_bp_list; static int16_t s_dpaa2_pool_ops_idx = RTE_MEMPOOL_MAX_OPS_IDX; +static int +dpaa2_mbuf_pool_mp_primary(const struct rte_mp_msg *msg, + const void *peer) +{ + struct rte_mp_msg reply; + const struct dpaa2_pool_mp_msg *req_msg = (const void *)msg->param; + struct dpaa2_pool_mp_msg *rsp_msg = (void *)reply.param; + + memset(&reply, 0, sizeof(reply)); + + switch (req_msg->msg_type) { + case DPAA2_POOL_OPS_IDX_REQ: + rsp_msg->msg_type = DPAA2_POOL_OPS_IDX_RSP; + rte_memcpy(rsp_msg->msg_data, &s_dpaa2_pool_ops_idx, + sizeof(s_dpaa2_pool_ops_idx)); + break; + default: + DPAA2_MEMPOOL_ERR("%s received invalid request(%d)", + __func__, req_msg->msg_type); + return -ENOTSUP; + } + + strlcpy(reply.name, DPAA2_POOL_MP_SYNC, sizeof(reply.name)); + return rte_mp_reply(&reply, peer); +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_mpool_get_ops_idx) int rte_dpaa2_mpool_get_ops_idx(void) { - return s_dpaa2_pool_ops_idx; + struct rte_mp_msg mp_req; + struct rte_mp_reply mp_reply; + struct timespec ts = {.tv_sec = 5, .tv_nsec = 0}; + int ret = 0; + struct dpaa2_pool_mp_msg *req_msg = (void *)mp_req.param; + struct dpaa2_pool_mp_msg *rsp_msg; + + if (rte_eal_process_type() == RTE_PROC_PRIMARY || + s_dpaa2_pool_ops_idx != RTE_MEMPOOL_MAX_OPS_IDX) + return s_dpaa2_pool_ops_idx; + + strlcpy(mp_req.name, DPAA2_POOL_MP_SYNC, sizeof(mp_req.name)); + req_msg->msg_type = DPAA2_POOL_OPS_IDX_REQ; + memset(&mp_reply, 0, sizeof(struct rte_mp_reply)); + ret = rte_mp_request_sync(&mp_req, &mp_reply, &ts); + if (ret) { + DPAA2_MEMPOOL_ERR("%s Failed to get response(%d)", + __func__, ret); + return ret; + } + if (!mp_reply.msgs) { + DPAA2_MEMPOOL_ERR("%s Failed to get response message", + __func__); + return -EINVAL; + } + rsp_msg = (void *)mp_reply.msgs; + if (rsp_msg->msg_type == DPAA2_POOL_OPS_IDX_RSP) { + rte_memcpy(&s_dpaa2_pool_ops_idx, rsp_msg->msg_data, + sizeof(s_dpaa2_pool_ops_idx)); + ret = 0; + } else { + DPAA2_MEMPOOL_ERR("%s received invalid response(%d)", + __func__, rsp_msg->msg_type); + ret = -EINVAL; + } + free(mp_reply.msgs); + + return ret; } static int @@ -128,10 +202,18 @@ rte_hw_mbuf_create_pool(struct rte_mempool *mp) if (s_dpaa2_pool_ops_idx == RTE_MEMPOOL_MAX_OPS_IDX) { s_dpaa2_pool_ops_idx = mp->ops_index; } else if (s_dpaa2_pool_ops_idx != mp->ops_index) { - DPAA2_MEMPOOL_ERR("Only single ops index only"); + DPAA2_MEMPOOL_ERR("Single ops index only"); ret = -EINVAL; goto err4; } + if (rte_eal_process_type() == RTE_PROC_PRIMARY && + !s_dpaa2_pool_mp_msg_setup) { + ret = rte_mp_action_register(DPAA2_POOL_MP_SYNC, + dpaa2_mbuf_pool_mp_primary); + if (ret && rte_errno != ENOTSUP) + return ret; + s_dpaa2_pool_mp_msg_setup = 1; + } bp_list->next = h_bp_list; bp_list->mp = mp; @@ -172,7 +254,7 @@ rte_hw_mbuf_free_pool(struct rte_mempool *mp) struct dpaa2_dpbp_dev *dpbp_node; if (!mp->pool_data) { - DPAA2_MEMPOOL_ERR("Not a valid dpaa2 buffer pool"); + DPAA2_MEMPOOL_ERR("Not a valid dpaa2 buffer pool %s", mp->name); return; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 14/47] net/dpaa2: set Tx confirmation on device init 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (12 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 13/47] mempool/dpaa2: support ops index from primary in secondary Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 15/47] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta ` (33 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f211357919..c95704d4ca 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3624,6 +3599,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 15/47] drivers: optimize dpaa2 Tx queue and channel mapping 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (13 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 14/47] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 16/47] net/dpaa2: support larger burst size Prashant Gupta ` (32 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Allocate TX queues based on dpni attribute and align the bounds check with the RX queue logic: - compute nb_tx_queues from num_tx_tcs * num_queues (respecting DPNI_OPT_SINGLE_SENDER) and cap at MAX_TX_QUEUES (128) - cap nb_rx_queues at MAX_RX_QUEUES (128) - cap num_channels at DPAA2_MAX_CHANNELS - assign tc_index/flow_id at queue-allocation time instead of at queue-setup time - replace the open-coded (channel << 8 | tc) with DPNI_BUILD_PARAM(channel, tc) throughout tx_queue_setup - initialize fqid to DPAA2_INVALID_FQ_ID and use it as the already-configured guard (replacing DPAA2_INVALID_FLOW_ID) - add a per-device tx_channels[] array for channel mapping Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/dpaa2_ethdev.c | 112 ++++++++++++++---------- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +- 3 files changed, 70 insertions(+), 48 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index ef65e7895a..f0bc9a3063 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -82,6 +82,7 @@ #define DPAA2_DPCI_MAX_QUEUES 2 #define DPAA2_INVALID_FLOW_ID 0xffff +#define DPAA2_INVALID_FQ_ID ((uint32_t)(-1)) #define DPAA2_INVALID_CGID 0xff #define SEC_FLC_DHR_OUTBOUND (-114) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c95704d4ca..d79dfa7114 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -519,17 +519,13 @@ static int dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint16_t dist_idx; - uint32_t vq_id; - uint8_t num_rxqueue_per_tc; - struct dpaa2_queue *mc_q, *mcq; + uint8_t num_queue_per_tc; + struct dpaa2_queue *mc_q, *dpaa2_q; uint32_t tot_queues; int i, ret = 0; - struct dpaa2_queue *dpaa2_q; PMD_INIT_FUNC_TRACE(); - num_rxqueue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); if (priv->flags & DPAA2_TX_CONF_ENABLE) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else @@ -541,8 +537,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) return -ENOBUFS; } + num_queue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); for (i = 0; i < priv->nb_rx_queues; i++) { mc_q->eth_data = dev->data; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->rx_vq[i] = mc_q++; dpaa2_q = priv->rx_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -566,9 +566,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } + num_queue_per_tc = (priv->nb_tx_queues / priv->num_tx_tc); for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->flow_id = DPAA2_INVALID_FLOW_ID; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_vq[i] = mc_q++; dpaa2_q = (struct dpaa2_queue *)priv->tx_vq[i]; dpaa2_q->cscn = rte_malloc(NULL, @@ -583,8 +586,9 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->tc_index = i; - mc_q->flow_id = 0; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_conf_vq[i] = mc_q++; dpaa2_q = priv->tx_conf_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -594,14 +598,6 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - vq_id = 0; - for (dist_idx = 0; dist_idx < priv->nb_rx_queues; dist_idx++) { - mcq = priv->rx_vq[vq_id]; - mcq->tc_index = dist_idx / num_rxqueue_per_tc; - mcq->flow_id = dist_idx % num_rxqueue_per_tc; - vq_id++; - } - return 0; fail_tx_conf: i -= 1; @@ -977,6 +973,12 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, return ret; } dpaa2_q = priv->rx_vq[rx_queue_id]; + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", + dev->data->name, rx_queue_id); + dev->data->rx_queues[rx_queue_id] = dpaa2_q; + return 0; + } dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1165,7 +1167,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->offloads = tx_conf->offloads; /* Return if queue already configured */ - if (dpaa2_q->flow_id != DPAA2_INVALID_FLOW_ID) { + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: TXQ[%d] has been setup", + dev->data->name, tx_queue_id); dev->data->tx_queues[tx_queue_id] = dpaa2_q; return 0; } @@ -1173,26 +1177,24 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - tc_id = tx_queue_id % priv->num_tx_tc; - channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; - flow_id = 0; + tc_id = dpaa2_q->tc_index; + flow_id = dpaa2_q->flow_id; + if (tc_id < priv->num_channels) + channel_id = priv->tx_channels[tc_id]; + else + channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); if (ret) { - DPAA2_PMD_ERR("Error in setting the tx flow: " - "tc_id=%d, flow=%d err=%d", - tc_id, flow_id, ret); - return ret; + DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", + ret, dev->data->name, tc_id, flow_id); + return ret; } - dpaa2_q->flow_id = flow_id; - - dpaa2_q->tc_index = tc_id; - ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, ((channel_id << 8) | dpaa2_q->tc_index), - dpaa2_q->flow_id, &tx_flow_cfg, &qid); + DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1231,10 +1233,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_set_congestion_notification(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), &cong_notif_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), &cong_notif_cfg); if (ret) { - DPAA2_PMD_ERR("Set TX congestion notification err=%d", - ret); + DPAA2_PMD_ERR("Set TX congestion notification err=%d", ret); return ret; } } @@ -1242,31 +1243,32 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dev->data->tx_queues[tx_queue_id] = dpaa2_q; if (priv->flags & DPAA2_TX_CONF_ENABLE) { + tc_id = dpaa2_tx_conf_q->tc_index; + flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; options = options | DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, - options, &tx_conf_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, options, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", - dpaa2_tx_conf_q->tc_index, - dpaa2_tx_conf_q->flow_id, ret); + tc_id, flow_id, ret); return ret; } ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, &tx_conf_cfg, &qid); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_conf_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; } dpaa2_tx_conf_q->fqid = qid.fqid; } + return 0; } @@ -3553,10 +3555,28 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; - for (i = 0; i < attr.num_rx_tcs; i++) - priv->nb_rx_queues += attr.num_queues; - - priv->nb_tx_queues = attr.num_tx_tcs * attr.num_channels; + priv->nb_rx_queues = attr.num_rx_tcs * attr.num_queues; + if (priv->nb_rx_queues > MAX_RX_QUEUES) { + DPAA2_PMD_WARN("Too many RXQs(%d) > %d, reduce it to %d", + priv->nb_rx_queues, MAX_RX_QUEUES, MAX_RX_QUEUES); + priv->nb_rx_queues = MAX_RX_QUEUES; + } + if (attr.options & DPNI_OPT_SINGLE_SENDER) + priv->nb_tx_queues = attr.num_tx_tcs * 1; + else + priv->nb_tx_queues = attr.num_tx_tcs * attr.num_queues; + if (priv->nb_tx_queues > MAX_TX_QUEUES) { + DPAA2_PMD_WARN("Too many TXQs(%d) > %d, reduce it to %d", + priv->nb_tx_queues, MAX_TX_QUEUES, MAX_TX_QUEUES); + priv->nb_tx_queues = MAX_TX_QUEUES; + } + if (priv->num_channels > DPAA2_MAX_CHANNELS) { + DPAA2_PMD_WARN("Too many TX channels(%d) > %d, reduce it to %d", + priv->num_channels, DPAA2_MAX_CHANNELS, DPAA2_MAX_CHANNELS); + priv->num_channels = DPAA2_MAX_CHANNELS; + } + for (i = 0; i < priv->num_channels; i++) + priv->tx_channels[i] = i; DPAA2_PMD_DEBUG("RX-TC= %d, rx_queues= %d, tx_queues=%d, max_cgs=%d", priv->num_rx_tc, priv->nb_rx_queues, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..0366315ec7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -28,7 +28,7 @@ #define MAX_TCS DPNI_MAX_TC #define MAX_RX_QUEUES 128 -#define MAX_TX_QUEUES 16 +#define MAX_TX_QUEUES 128 #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 @@ -390,13 +390,14 @@ struct dpaa2_dev_priv { int32_t hw_id; int32_t qdid; uint16_t token; + uint16_t tx_channels[DPAA2_MAX_CHANNELS]; uint8_t nb_tx_queues; uint8_t nb_rx_queues; uint32_t options; void *rx_vq[MAX_RX_QUEUES]; void *tx_vq[MAX_TX_QUEUES]; struct dpaa2_bp_list *bp_list; /**<Attached buffer pool list */ - void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; + void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ uint8_t max_mac_filters; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 16/47] net/dpaa2: support larger burst size 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (14 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 15/47] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 17/47] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (31 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..41b0f99a90 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (priv->dpni_ver_major == 8 && priv->dpni_ver_minor >= 7) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : (64 * 1024); + + return 64 * 1024; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 17/47] net/dpaa2: support MPLS and PPPoE flow distribution 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (15 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 16/47] net/dpaa2: support larger burst size Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 18/47] net/dpaa2: support meter and policing Prashant Gupta ` (30 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 63c253ab3b..b168a69ed5 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -81,6 +81,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -181,8 +183,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1765,6 +1776,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4042,6 +4061,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4713,6 +4889,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 18/47] net/dpaa2: support meter and policing 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (16 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 17/47] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 19/47] net/dpaa2: support flow drop action Prashant Gupta ` (29 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API to the dpaa2 PMD. The implementation registers the rte_mtr operations through the ".mtr_ops_get" dev_ops hook and maintains software bookkeeping of meter profiles, policies and meter objects under a per-device spinlock. Supported algorithms are trTCM RFC 2698 and trTCM RFC 4115 in both byte and packet modes. Meter policies support drop and pass-through actions on the red color. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 1 + drivers/net/dpaa2/dpaa2_ethdev.h | 29 ++ drivers/net/dpaa2/dpaa2_meter.c | 588 +++++++++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 23 +- drivers/net/dpaa2/meson.build | 1 + 5 files changed, 638 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index d79dfa7114..c8abab830f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3322,6 +3322,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 0366315ec7..c5aac65c28 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + int red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -412,6 +436,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -457,6 +482,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -549,6 +577,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..aae88a4d4b --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,588 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = true, + .color_aware_trtcm_rfc4115_supported = true, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /** Align with DPNI policy.*/ + if (!profile->packet_mode) { + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + } else if (profile->packet_mode > DPNI_POLICER_UNIT_FRAMES) { + dpaa2_profile->policer_unit = + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS; + } else { + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + } + + dpaa2_profile->profile_id = profile_id; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter, *tmp; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + DPAA2_PMD_INFO("Meter(id=%d) with profile(%d) is removed!", + meter->meter_id, profile_id); + tmp = meter; + meter = LIST_NEXT(meter, next); + LIST_REMOVE(tmp, next); + rte_free(tmp); + } else { + meter = LIST_NEXT(meter, next); + } + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter, *tmp; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + DPAA2_PMD_INFO("Meter(id=%d) with policy(%d) is removed!", + meter->meter_id, policy_id); + tmp = meter; + meter = LIST_NEXT(meter, next); + LIST_REMOVE(tmp, next); + rte_free(tmp); + } else { + meter = LIST_NEXT(meter, next); + } + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + rte_spinlock_init(&priv->meter_lock); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..d227025e01 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ +#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004 + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1132,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1183,18 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); +int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 19/47] net/dpaa2: support flow drop action 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (17 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 18/47] net/dpaa2: support meter and policing Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 20/47] net/dpaa2: set default flow miss action per device Prashant Gupta ` (28 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b168a69ed5..07ecdd0e7b 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -98,7 +98,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4422,6 +4423,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4469,6 +4471,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4946,6 +4950,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5347,6 +5352,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 20/47] net/dpaa2: set default flow miss action per device 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (18 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 19/47] net/dpaa2: support flow drop action Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 21/47] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (27 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global configured only via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable and defaulted to 0. Replace it with a per-device default_flow computed at probe time as the lowest priority flow of the FS table, so that unmatched frames are directed there without depending on an environment variable. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c8abab830f..387a153036 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3545,6 +3545,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MIN(priv->fs_entries, + priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c5aac65c28..4501bd9e49 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -437,6 +437,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 07ecdd0e7b..750b93498b 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -25,7 +25,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4591,7 +4590,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5225,17 +5224,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 21/47] net/dpaa2: identify Rx mbuf hash information by FLC 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (19 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 20/47] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 22/47] net/dpaa2: add minimum key size support Prashant Gupta ` (26 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC for mbuf Rx scheduling. An Rx mbuf received from the FS table is marked with RTE_MBUF_F_RX_FDIR along with the TC and flow ID decoded from the FLC low word. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 4501bd9e49..c693989998 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 750b93498b..dfe1774d25 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4384,6 +4384,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4446,6 +4453,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4453,7 +4461,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..7ba6a4563f 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, 0); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 22/47] net/dpaa2: add minimum key size support 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (20 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 21/47] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 23/47] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (25 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index dfe1774d25..016a1e98b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -27,8 +27,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4533,8 +4536,7 @@ dpaa2_flow_entry_size(uint16_t key_max_size) if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 23/47] net/dpaa2: restructure dpaa2 parser processing 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (21 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 22/47] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 24/47] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (24 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move the parse-result decoding into a dedicated header so that the hardware parser fields are described in one place and shared between the flow code and the Rx path. No functional change is intended. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 172 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1545 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 332 ++--- 4 files changed, 1845 insertions(+), 578 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c693989998..ddc1917b23 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,17 +207,33 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; -extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ @@ -258,42 +308,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -436,6 +450,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -475,6 +490,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -483,6 +501,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -514,6 +533,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + fprintf(rte_log_get_stream(), "Directed to TC%d-flow%d(rxq%d), color(%d)\n", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + fprintf(rte_log_get_stream(), "Balanced with hash(0x%08x)\n", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..6c7513f8f6 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1545 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_log.h> +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +/* Parser-result dumps are emitted as partial lines built up in loops, so + * they cannot use the line-oriented RTE_LOG_LINE helpers. Write to the EAL + * log stream instead of stdout so the output follows the configured log + * destination. + */ +#define DPAA2_PR_PRINT(...) fprintf(rte_log_get_stream(), __VA_ARGS__) + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_L4_NONFRAG; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type &= ~RTE_PTYPE_L4_NONFRAG; + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 7ba6a4563f..47c8cacdc4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,19 +26,43 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" +#include "dpaa2_parser_decode.h" -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} -static inline rte_mbuf_timestamp_t * -dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) { - return RTE_MBUF_DYNFIELD(mbuf, - dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; } #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ @@ -51,95 +75,108 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) + +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, DPAA2_GET_FD_DROPP(fd)); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + RTE_SET_USED(priv); m->packet_type = RTE_PTYPE_UNKNOWN; + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); - } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - m->ol_flags |= RTE_MBUF_F_RX_FDIR; - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - rte_mbuf_sched_set(m, flow, tc, 0); - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + m->packet_type = dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; } - if (dpaa2_enable_ts[m->port]) { - *dpaa2_timestamp_dynfield(m) = annotation->word2; - m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + *(rte_be64_t *)&word5 = rte_cpu_to_be_64(annotation->word5); + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -249,36 +286,18 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + annotation->word4); - if (dpaa2_enable_ts[mbuf->port]) { - *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; - mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(mbuf)); - } + RTE_SET_USED(priv); /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -307,8 +326,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -336,12 +354,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -381,13 +401,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -397,7 +426,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -413,9 +442,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -674,6 +704,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -729,15 +760,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -792,18 +824,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -909,18 +935,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -989,7 +1014,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1014,7 +1042,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1041,7 +1072,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1151,12 +1185,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1164,6 +1201,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1314,7 +1352,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1336,7 +1374,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1617,8 +1655,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 24/47] net/dpaa2: parse tunnel and fragmented packet types 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (22 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 23/47] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 25/47] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (23 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend the Rx parser to identify additional packet types decoded from the hardware parser summary: IPv4/IPv6 fragments, IPsec ESP, and GTP-U / GTP-C tunnels. The corresponding DPAA2_PKT_TYPE_* values are added and mapped to the matching RTE_PTYPE_* flags in the slow-path parser. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index ddc1917b23..c298954265 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 47c8cacdc4..26c84e7125 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -153,6 +153,38 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPC; + break; case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 25/47] net/dpaa2: remove unused soft parser driver 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (23 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 24/47] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 26/47] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta ` (22 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Softparser only supports to be loaded before Linux starts. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 28 ----- drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 -------------------- drivers/net/dpaa2/dpaa2_sparser.h | 202 ------------------------------ drivers/net/dpaa2/meson.build | 1 - 5 files changed, 369 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 387a153036..1df84e1316 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3738,33 +3737,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 80c20272ce..ed038c204b 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 26/47] drivers: refresh dpaa2 MC and SoC version info 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (24 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 25/47] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 27/47] drivers: identify dpaa2 soft parser protocol Prashant Gupta ` (21 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Fix MC revision typo to correct major to minor. Get MC/SoC rev info only once and save them in bus info as well as other information to reduce replicated variables. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 11 +- drivers/bus/fslmc/fslmc_bus.c | 2 + drivers/bus/fslmc/fslmc_vfio.c | 200 ++++++++++++++++++----- drivers/bus/fslmc/fslmc_vfio.h | 30 +++- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 79 +-------- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 7 - drivers/bus/fslmc/private.h | 3 + drivers/net/dpaa2/dpaa2_ethdev.c | 18 +- drivers/net/dpaa2/dpaa2_ethdev.h | 1 + drivers/net/dpaa2/dpaa2_rxtx.c | 10 +- 10 files changed, 225 insertions(+), 136 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 44f81cf662..3ba865e632 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2021-2023 NXP + * Copyright 2016,2021-2026 NXP * */ @@ -89,6 +89,14 @@ enum rte_dpaa2_dev_type { DPAA2_DEVTYPE_MAX, }; +struct rte_fslmc_bus_info { + void *mem_pool; + int sp_protocol; + uint64_t mc_rev; + uint32_t svr; + uint32_t pvr; +}; + /** * A structure describing a DPAA2 device. */ @@ -102,6 +110,7 @@ struct rte_dpaa2_device { char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ + const struct rte_fslmc_bus_info *bus_info; }; typedef int (*rte_dpaa2_obj_create_t)(int vdev_fd, diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index ee162b0ed8..2427421075 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -29,6 +29,7 @@ struct rte_bus rte_fslmc_bus; static int fslmc_bus_device_count[DPAA2_DEVTYPE_MAX]; +struct rte_fslmc_bus_info fslmc_bus_info; #define DPAA2_SEQN_DYNFIELD_NAME "dpaa2_seqn_dynfield" RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) @@ -199,6 +200,7 @@ scan_one_fslmc_device(char *dev_name) goto cleanup; } dev->device.devargs = rte_bus_find_devargs(&rte_fslmc_bus, dev_name); + dev->bus_info = &fslmc_bus_info; /* Update the device found into the device_count table */ fslmc_bus_device_count[dev->dev_type]++; diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index 412b70e5ae..4eb8552696 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -87,6 +87,83 @@ enum { FSLMC_VFIO_SOCKET_REQ_MEM }; +/* Variable to store DPAA2 platform type */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) +uint32_t dpaa2_svr_family; + +/* Variable to store DPAA2 DQRR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) +uint32_t dpaa2_dqrr_size; +/* Variable to store DPAA2 EQCR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) +uint32_t dpaa2_eqcr_size; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_base) +uint32_t dpaa2_cluster_base; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_size) +uint32_t dpaa2_cluster_size; + +struct fslmc_soc_type { + uint32_t svr; + uint32_t cluster_base; + uint32_t cluster_size; + uint32_t qm_dq_size; + uint32_t qm_eq_size; +}; + +/* For LS208X platform There are four clusters with following mapping: + * Cluster 1 (ID = x04) : CPU0, CPU1; + * Cluster 2 (ID = x05) : CPU2, CPU3; + * Cluster 3 (ID = x06) : CPU4, CPU5; + * Cluster 4 (ID = x07) : CPU6, CPU7; + */ +/* For LS108X platform There are two clusters with following mapping: + * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; + * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; + */ +/* For LX2160 platform There are four clusters with following mapping: + * Cluster 1 (ID = x00) : CPU0, CPU1; + * Cluster 2 (ID = x01) : CPU2, CPU3; + * Cluster 3 (ID = x02) : CPU4, CPU5; + * Cluster 4 (ID = x03) : CPU6, CPU7; + * Cluster 1 (ID = x04) : CPU8, CPU9; + * Cluster 2 (ID = x05) : CPU10, CP11; + * Cluster 3 (ID = x06) : CPU12, CPU13; + * Cluster 4 (ID = x07) : CPU14, CPU15; + */ + +int +fslmc_vfio_core_cluster_sdest(uint32_t cpu_id) +{ + int x = cpu_id / dpaa2_cluster_size; + + if (!dpaa2_cluster_size) { + DPAA2_BUS_ERR("SoC type has not been initialized!"); + + return -ENODEV; + } + + return dpaa2_cluster_base + x; +} + +static const struct fslmc_soc_type s_soc_type[] = { + { + SVR_LS2080A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS2088A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS1080A, 2, 4, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LX2160A, 0, 2, + DPAA2_LX2_DQRR_RING_SIZE, DPAA2_LX2_EQCR_RING_SIZE + } +}; + RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_get_mcp_ptr) void * dpaa2_get_mcp_ptr(int portal_idx) @@ -168,6 +245,70 @@ rte_fslmc_object_register(struct rte_dpaa2_object *object) TAILQ_INSERT_TAIL(&dpaa2_obj_list, object, next); } +static int +fslmc_vfio_get_bus_info(void *regs, struct rte_fslmc_bus_info *bus_info) +{ + struct fsl_mc_io mc_io; + struct mc_version mc_ver_info = {0}; + struct mc_soc_version mc_plat_info; + int ret; + size_t i; + + mc_io.regs = regs; + + ret = mc_get_version(&mc_io, CMD_PRI_LOW, &mc_ver_info); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to obtain MC version.", ret); + return ret; + } + DPAA2_BUS_INFO("MC version is %d.%d.%d.", mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + bus_info->mc_rev = RTE_FSL_MC_REV(mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + if (bus_info->mc_rev < RTE_FSL_MC_REV(MC_VER_MAJOR, MC_VER_MINOR, 0)) { + DPAA2_BUS_ERR("DPAA2 MC version not compatible! %d.%d.%d < %d.%d.0", + mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, + MC_VER_MAJOR, MC_VER_MINOR); + return -EPERM; + } + + memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); + ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); + if (ret) { + DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); + return ret; + } + + memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); + ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); + if (ret) { + DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); + return ret; + } + + for (i = 0; i < RTE_DIM(s_soc_type); i++) { + if ((mc_plat_info.svr & DPAA2_SVR_MASK) == s_soc_type[i].svr) { + dpaa2_svr_family = s_soc_type[i].svr; + dpaa2_cluster_base = s_soc_type[i].cluster_base; + dpaa2_cluster_size = s_soc_type[i].cluster_size; + dpaa2_dqrr_size = s_soc_type[i].qm_dq_size; + dpaa2_eqcr_size = s_soc_type[i].qm_eq_size; + break; + } + } + if (i == RTE_DIM(s_soc_type)) { + DPAA2_BUS_ERR("Invalid SoC version: 0x%08x", mc_plat_info.svr); + return -ENODEV; + } + + bus_info->svr = mc_plat_info.svr; + bus_info->pvr = mc_plat_info.pvr; + + return 0; +} + static const char * fslmc_vfio_get_group_name(void) { @@ -1247,9 +1388,9 @@ fslmc_vfio_setup_device(const char *dev_addr, dev_addr); } -static intptr_t vfio_map_mcp_obj(const char *mcp_obj) +static void *fslmc_vfio_map_mcp_obj(const char *mcp_obj) { - intptr_t v_addr = (intptr_t)MAP_FAILED; + void *v_addr = MAP_FAILED; int32_t ret, mc_fd; struct vfio_group_status status = { .argsz = sizeof(status) }; @@ -1265,7 +1406,7 @@ static intptr_t vfio_map_mcp_obj(const char *mcp_obj) goto MC_FAILURE; } - v_addr = (size_t)mmap(NULL, reg_info.size, + v_addr = mmap(NULL, reg_info.size, PROT_WRITE | PROT_READ, MAP_SHARED, mc_fd, reg_info.offset); @@ -1388,7 +1529,7 @@ rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, } static void -fslmc_close_iodevices(struct rte_dpaa2_device *dev, +fslmc_vfio_close_iodevices(struct rte_dpaa2_device *dev, int vfio_fd) { struct rte_dpaa2_object *object = NULL; @@ -1431,11 +1572,11 @@ fslmc_close_iodevices(struct rte_dpaa2_device *dev, } /* - * fslmc_process_iodevices for processing only IO (ETH, CRYPTO, and possibly + * fslmc_vfio_process_iodevices for processing only IO (ETH, CRYPTO, and possibly * EVENT) devices. */ static int -fslmc_process_iodevices(struct rte_dpaa2_device *dev) +fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev) { int dev_fd, ret; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; @@ -1477,12 +1618,10 @@ fslmc_process_iodevices(struct rte_dpaa2_device *dev) } static int -fslmc_process_mcp(struct rte_dpaa2_device *dev) +fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev) { int ret; - intptr_t v_addr; - struct fsl_mc_io dpmng = {0}; - struct mc_version mc_ver_info = {0}; + void *v_addr; rte_mcp_ptr_list = malloc(sizeof(void *) * (MC_PORTAL_INDEX + 1)); if (!rte_mcp_ptr_list) { @@ -1491,15 +1630,16 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) goto cleanup; } - v_addr = vfio_map_mcp_obj(dev->device.name); - if (v_addr == (intptr_t)MAP_FAILED) { + v_addr = fslmc_vfio_map_mcp_obj(dev->device.name); + if (v_addr == MAP_FAILED) { DPAA2_BUS_ERR("Error mapping region (errno = %d)", errno); ret = -1; goto cleanup; } - /* check the MC version compatibility */ - dpmng.regs = (void *)v_addr; + ret = fslmc_vfio_get_bus_info(v_addr, &fslmc_bus_info); + if (ret) + goto cleanup; /* In case of secondary processes, MC version check is no longer * required. @@ -1509,23 +1649,7 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) return 0; } - if (mc_get_version(&dpmng, CMD_PRI_LOW, &mc_ver_info)) { - DPAA2_BUS_ERR("Unable to obtain MC version"); - ret = -1; - goto cleanup; - } - - if ((mc_ver_info.major != MC_VER_MAJOR) || - (mc_ver_info.minor < MC_VER_MINOR)) { - DPAA2_BUS_ERR("DPAA2 MC version not compatible!" - " Expected %d.%d.x, Detected %d.%d.%d", - MC_VER_MAJOR, MC_VER_MINOR, - mc_ver_info.major, mc_ver_info.minor, - mc_ver_info.revision); - ret = -1; - goto cleanup; - } - rte_mcp_ptr_list[MC_PORTAL_INDEX] = (void *)v_addr; + rte_mcp_ptr_list[MC_PORTAL_INDEX] = v_addr; return 0; @@ -1567,7 +1691,7 @@ fslmc_vfio_close_group(void) case DPAA2_CRYPTO: case DPAA2_QDMA: case DPAA2_IO: - fslmc_close_iodevices(dev, vfio_group_fd); + fslmc_vfio_close_iodevices(dev, vfio_group_fd); break; case DPAA2_CON: case DPAA2_CI: @@ -1576,7 +1700,7 @@ fslmc_vfio_close_group(void) if (rte_eal_process_type() == RTE_PROC_SECONDARY) continue; - fslmc_close_iodevices(dev, vfio_group_fd); + fslmc_vfio_close_iodevices(dev, vfio_group_fd); break; case DPAA2_DPRTC: default: @@ -1639,7 +1763,7 @@ fslmc_vfio_process_group(void) } if (!found_mportal) { - ret = fslmc_process_mcp(dev); + ret = fslmc_vfio_process_mcp(dev); if (ret) { DPAA2_BUS_ERR("Unable to map MC Portal"); return ret; @@ -1668,7 +1792,7 @@ fslmc_vfio_process_group(void) current_device = 0; RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { if (dev->dev_type == DPAA2_DPRC) { - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_ERR("Unable to process dprc"); return ret; @@ -1700,7 +1824,7 @@ fslmc_vfio_process_group(void) case DPAA2_ETH: case DPAA2_CRYPTO: case DPAA2_QDMA: - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); @@ -1723,7 +1847,7 @@ fslmc_vfio_process_group(void) /* Call the object creation routine and remove the * device entry from device list */ - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); @@ -1747,7 +1871,7 @@ fslmc_vfio_process_group(void) } } - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h index c995fd67b8..554123ffa6 100644 --- a/drivers/bus/fslmc/fslmc_vfio.h +++ b/drivers/bus/fslmc/fslmc_vfio.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019-2023 NXP + * Copyright 2016,2019-2026 NXP * */ @@ -9,6 +9,8 @@ #define _FSLMC_VFIO_H_ #include <rte_compat.h> +#include <rte_vfio.h> +#include <rte_interrupts.h> /* Pathname of FSL-MC devices directory. */ #define SYSFS_FSL_MC_DEVICES "/sys/bus/fsl-mc/devices" @@ -44,6 +46,30 @@ struct fslmc_vfio_container { extern char *fslmc_container; +extern uint32_t dpaa2_svr_family; +extern uint32_t dpaa2_dqrr_size; +extern uint32_t dpaa2_eqcr_size; +extern uint32_t dpaa2_cluster_base; +extern uint32_t dpaa2_cluster_size; + +#define DPAA2_SVR_MASK 0xffff0000 + +#define SVR_LS1080A 0x87030000 +#define SVR_LS2080A 0x87010000 +#define SVR_LS2088A 0x87090000 +#define SVR_LX2160A 0x87360000 + +#define MC_MAJOR_OFFSET 32 +#define MC_MINOR_OFFSET 16 +#define MC_MINOR_MASK ((((uint64_t)1) << (MC_MAJOR_OFFSET - MC_MINOR_OFFSET)) - 1) +#define MC_REVISION_MASK ((((uint64_t)1) << MC_MINOR_OFFSET) - 1) +#define RTE_FSL_MC_REV(major, minor, revision) \ + ((((uint64_t)(major)) << MC_MAJOR_OFFSET) + \ + (((uint64_t)(minor)) << MC_MINOR_OFFSET) + (revision)) +#define RTE_FSL_MC_REV_MAJOR(rev) ((uint32_t)((rev) >> MC_MAJOR_OFFSET)) +#define RTE_FSL_MC_REV_MINOR(rev) ((uint32_t)(((rev) >> MC_MINOR_OFFSET) & MC_MINOR_MASK)) +#define RTE_FSL_MC_REV_REVISION(rev) ((uint32_t)((rev) & MC_REVISION_MASK)) + __rte_internal int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index); @@ -60,4 +86,6 @@ int fslmc_vfio_close_group(void); char *fslmc_get_container(void); int fslmc_get_container_group(const char *group_name, int *gropuid); int fslmc_vfio_dmamap(void); +int fslmc_vfio_core_cluster_sdest(uint32_t cpu_id); + #endif /* _FSLMC_VFIO_H_ */ diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index e17050b625..20d1bb2a66 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2022 NXP + * Copyright 2016-2026 NXP * */ #include <uapi/linux/vfio.h> @@ -63,45 +63,9 @@ static struct dpio_dev_list dpio_dev_list = TAILQ_HEAD_INITIALIZER(dpio_dev_list); /*!< DPIO device list */ static uint32_t io_space_count; -/* Variable to store DPAA2 platform type */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) -uint32_t dpaa2_svr_family; - -/* Variable to store DPAA2 DQRR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) -uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) -uint8_t dpaa2_eqcr_size; - /* Variable to hold the portal_key, once created.*/ static pthread_key_t dpaa2_portal_key; -/*Stashing Macros default for LS208x*/ -static int dpaa2_core_cluster_base = 0x04; -static int dpaa2_cluster_sz = 2; - -/* For LS208X platform There are four clusters with following mapping: - * Cluster 1 (ID = x04) : CPU0, CPU1; - * Cluster 2 (ID = x05) : CPU2, CPU3; - * Cluster 3 (ID = x06) : CPU4, CPU5; - * Cluster 4 (ID = x07) : CPU6, CPU7; - */ -/* For LS108X platform There are two clusters with following mapping: - * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; - * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; - */ -/* For LX2160 platform There are four clusters with following mapping: - * Cluster 1 (ID = x00) : CPU0, CPU1; - * Cluster 2 (ID = x01) : CPU2, CPU3; - * Cluster 3 (ID = x02) : CPU4, CPU5; - * Cluster 4 (ID = x03) : CPU6, CPU7; - * Cluster 1 (ID = x04) : CPU8, CPU9; - * Cluster 2 (ID = x05) : CPU10, CP11; - * Cluster 3 (ID = x06) : CPU12, CPU13; - * Cluster 4 (ID = x07) : CPU14, CPU15; - */ - static struct dpaa2_dpio_dev *get_dpio_dev_from_id(int32_t dpio_id) { struct dpaa2_dpio_dev *dpio_dev = NULL; @@ -141,14 +105,6 @@ dpaa2_get_core_id(void) return cpu_id; } -static int -dpaa2_core_cluster_sdest(int cpu_id) -{ - int x = cpu_id / dpaa2_cluster_sz; - - return dpaa2_core_cluster_base + x; -} - static void dpaa2_affine_dpio_intr_to_respective_core(int32_t dpio_id, int cpu_id) { @@ -307,15 +263,17 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx /* Set the STASH Destination depending on Current CPU ID. * Valid values of SDEST are 4,5,6,7. Where, */ - sdest = dpaa2_core_cluster_sdest(cpu_id); + sdest = fslmc_vfio_core_cluster_sdest(cpu_id); DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", dpio_dev->index, cpu_id, sdest); + if (sdest < 0) + return sdest; ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token, sdest); if (ret) { DPAA2_BUS_ERR("%d ERROR in SDEST", ret); - return -1; + return ret; } #ifdef RTE_EVENT_DPAA2 @@ -542,33 +500,6 @@ dpaa2_create_dpio_device(int vdev_fd, goto err; } - /* find the SoC type for the first time */ - if (!dpaa2_svr_family) { - struct mc_soc_version mc_plat_info = {0}; - - if (mc_get_soc_version(dpio_dev->dpio, - CMD_PRI_LOW, &mc_plat_info)) { - DPAA2_BUS_ERR("Unable to get SoC version information"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LS1080A) { - dpaa2_core_cluster_base = 0x02; - dpaa2_cluster_sz = 4; - DPAA2_BUS_DEBUG("LS108x (A53) Platform Detected"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LX2160A) { - dpaa2_core_cluster_base = 0x00; - dpaa2_cluster_sz = 2; - DPAA2_BUS_DEBUG("LX2160 Platform Detected"); - } - dpaa2_svr_family = (mc_plat_info.svr & 0xffff0000); - - if (dpaa2_svr_family == SVR_LX2160A) { - dpaa2_dqrr_size = DPAA2_LX2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_LX2_EQCR_RING_SIZE; - } else { - dpaa2_dqrr_size = DPAA2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_EQCR_RING_SIZE; - } - } - if (dpaa2_svr_family == SVR_LX2160A) reg_info.index = DPAA2_SWP_CENA_MEM_REGION; else diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 7e2271cc35..2c559e5354 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -35,13 +35,6 @@ RTE_DECLARE_PER_LCORE(struct dpaa2_io_portal_t, _dpaa2_io); #define DPAA2_PER_LCORE_DQRR_MBUF(i) \ RTE_PER_LCORE(_dpaa2_io).dpio_dev->dpaa2_held_bufs.mbuf[i] -/* Variable to store DPAA2 DQRR size */ -extern uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -extern uint8_t dpaa2_eqcr_size; - -extern struct dpaa2_io_portal_t dpaa2_io_portal[RTE_MAX_LCORE]; - /* Affine a DPIO portal to current processing thread */ __rte_internal int dpaa2_affine_qbman_swp(void); diff --git a/drivers/bus/fslmc/private.h b/drivers/bus/fslmc/private.h index 20a454c3fc..1c8a3e59e9 100644 --- a/drivers/bus/fslmc/private.h +++ b/drivers/bus/fslmc/private.h @@ -11,4 +11,7 @@ extern struct rte_bus rte_fslmc_bus; +/* MC/SoC version and capability info, shared by the bus and VFIO code. */ +extern struct rte_fslmc_bus_info fslmc_bus_info; + #endif /* BUS_FSLMC_PRIVATE_H */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 1df84e1316..e6ce29b2ea 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -329,24 +329,21 @@ dpaa2_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size) { int ret; + uint32_t major, minor, rev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = dev->process_private; struct mc_soc_version mc_plat_info = {0}; - struct mc_version mc_ver_info = {0}; PMD_INIT_FUNC_TRACE(); + major = RTE_FSL_MC_REV_MAJOR(priv->mc_rev); + minor = RTE_FSL_MC_REV_MINOR(priv->mc_rev); + rev = RTE_FSL_MC_REV_REVISION(priv->mc_rev); if (mc_get_soc_version(dpni, CMD_PRI_LOW, &mc_plat_info)) DPAA2_PMD_WARN("\tmc_get_soc_version failed"); - if (mc_get_version(dpni, CMD_PRI_LOW, &mc_ver_info)) - DPAA2_PMD_WARN("\tmc_get_version failed"); - - ret = snprintf(fw_version, fw_size, - "%x-%d.%d.%d", - mc_plat_info.svr, - mc_ver_info.major, - mc_ver_info.minor, - mc_ver_info.revision); + ret = snprintf(fw_version, fw_size, "%x-%d.%d.%d", + mc_plat_info.svr, major, minor, rev); if (ret < 0) return -EINVAL; @@ -3537,6 +3534,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + priv->mc_rev = dpaa2_dev->bus_info->mc_rev; priv->num_rx_tc = attr.num_rx_tcs; priv->num_tx_tc = attr.num_tx_tcs; priv->qos_entries = attr.qos_entries; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c298954265..9c52a6c248 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -528,6 +528,7 @@ struct dpaa2_dev_priv { uint32_t *cnt_idx_dma_mem; uint64_t *cnt_values_dma_mem; uint64_t cnt_idx_iova, cnt_values_iova; + uint64_t mc_rev; struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 26c84e7125..f417edf52b 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1123,9 +1123,9 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, /* Function receive frames for a given device and VQ */ struct dpaa2_queue *dpaa2_q = queue; struct qbman_result *dq_storage; - uint32_t fqid = dpaa2_q->fqid; - int ret, num_rx = 0, next_pull = nb_pkts, num_pulled; - uint8_t pending, status; + uint32_t fqid = dpaa2_q->fqid, next_pull = nb_pkts; + int ret; + uint8_t pending, status, num_rx = 0, num_pulled; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; @@ -1269,8 +1269,8 @@ uint16_t dpaa2_dev_tx_conf(void *queue) struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; struct qbman_result *dq_storage; uint32_t fqid = dpaa2_q->fqid; - int ret, num_tx_conf = 0, num_pulled; - uint8_t pending, status; + int ret, num_tx_conf = 0; + uint8_t pending, status, num_pulled; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 27/47] drivers: identify dpaa2 soft parser protocol 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (25 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 26/47] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 28/47] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta ` (20 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Identify if soft parser protocol firmware is loaded by checking firmware magic number. Enable flow/parser of ECPRI, GENEVE, ROCEv2 and VXLAN's spec only with soft parser protocol firmware being loaded. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/fslmc_bus.c | 83 +++++++++++++++++++- drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_flow.c | 129 ++++++++----------------------- drivers/net/dpaa2/dpaa2_rxtx.c | 10 +++ 4 files changed, 126 insertions(+), 98 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index 2427421075..9742b0bfbf 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2018-2021 NXP + * Copyright 2016,2018-2026 NXP * */ @@ -8,6 +8,7 @@ #include <dirent.h> #include <stdalign.h> #include <stdbool.h> +#include <sys/mman.h> #include <eal_export.h> #include <rte_log.h> @@ -35,6 +36,85 @@ struct rte_fslmc_bus_info fslmc_bus_info; RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) int dpaa2_seqn_dynfield_offset = -1; +/** For LX2160A, LS2088A and LS1088A*/ +#define WRIOP_CCSR_BASE 0x8b80000 +#define WRIOP_CCSR_CTLU_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 + +#define WRIOP_INGRESS_PARSER_PHY \ + (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) + +struct __rte_packed_begin dpaa2_parser_ccsr { + uint32_t psr_cfg; + uint32_t psr_idle; + uint32_t psr_pclm; + uint8_t psr_ver_min; + uint8_t psr_ver_maj; + uint8_t psr_id1_l; + uint8_t psr_id1_h; + uint32_t psr_rev2; + uint8_t rsv[0x2c]; + uint8_t sp_ins[4032]; +} __rte_packed_end; + +#define SP_PROTOCOL_MAGIC_DATA 0xabcd +#define SP_PROTOCOL_MAGIC_OFFSET 0x4 + +static void +fslmc_soft_parser_protocol_supported(void) +{ + int fd, i; + void *map_addr = NULL; + const struct dpaa2_parser_ccsr *parser_ccsr = NULL; + const uint16_t *magic_num; + + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd < 0) { + DPAA2_BUS_ERR("open \"/dev/mem\" ERROR(%d)", fd); + goto exit; + } + + map_addr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, + WRIOP_INGRESS_PARSER_PHY); + parser_ccsr = map_addr; + if (!parser_ccsr) { + DPAA2_BUS_ERR("Map 0x%lx(size=0x%lx) failed", + (uint64_t)WRIOP_INGRESS_PARSER_PHY, + sizeof(struct dpaa2_parser_ccsr)); + goto exit; + } + + DPAA2_BUS_DEBUG("Soft ParserID:0x%02x%02x, Rev:maj(%02x), min(%02x)", + parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, + parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); + + magic_num = (const void *)&parser_ccsr->sp_ins[SP_PROTOCOL_MAGIC_OFFSET]; + if (*magic_num == SP_PROTOCOL_MAGIC_DATA) { + #define SP_PRINT_LEN 128 + + fslmc_bus_info.sp_protocol = true; + DPAA2_BUS_INFO("Soft parser protocol support."); + fprintf(rte_log_get_stream(), "First %d bytes of sp protocol firmware:\r\n", + SP_PRINT_LEN); + for (i = 0; i < SP_PRINT_LEN; i++) { + fprintf(rte_log_get_stream(), "%02x ", parser_ccsr->sp_ins[i]); + if ((i + 1) % 16 == 0) + fprintf(rte_log_get_stream(), "\r\n"); + } + fprintf(rte_log_get_stream(), "\r\n"); + } + +exit: + if (map_addr) + munmap(map_addr, sizeof(struct dpaa2_parser_ccsr)); + if (fd >= 0) + close(fd); +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_get_device_count) uint32_t rte_fslmc_get_device_count(enum rte_dpaa2_dev_type device_type) @@ -345,6 +425,7 @@ rte_fslmc_scan(void) DPAA2_BUS_ERR("Unable to open VFIO group directory"); goto scan_fail; } + fslmc_soft_parser_protocol_supported(); /* Scan the DPRC container object */ ret = scan_one_fslmc_device(group_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index e6ce29b2ea..fb1d01e209 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3735,6 +3735,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; + priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; + DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 016a1e98b4..06ec1a2660 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -10,7 +10,6 @@ #include <string.h> #include <unistd.h> #include <stdarg.h> -#include <sys/mman.h> #include <rte_ethdev.h> #include <rte_log.h> @@ -23,9 +22,9 @@ #include <dpaa2_ethdev.h> #include <dpaa2_pmd_logs.h> +#include "dpaa2_parser_decode.h" static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -435,92 +434,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -3539,6 +3452,11 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); + return -ENOTSUP; + } + ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_GRE); if (ret) { @@ -3584,6 +3502,11 @@ dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, struct dpaa2_dev_priv *priv = dev->data->dev_private; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -3682,6 +3605,11 @@ dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("ROCEV2 flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -4001,6 +3929,11 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -4726,7 +4659,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, static int dpaa2_flow_item_convert(const struct rte_flow_item pattern[], - struct rte_dpaa2_flow_item **dpaa2_pattern) + struct rte_dpaa2_flow_item **dpaa2_pattern, int sp_protocol) { struct rte_dpaa2_flow_item *new_pattern; int num = 0, tunnel_start = 0; @@ -4738,7 +4671,7 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], } new_pattern = rte_malloc(NULL, sizeof(struct rte_dpaa2_flow_item) * num, - RTE_CACHE_LINE_SIZE); + RTE_CACHE_LINE_SIZE); if (!new_pattern) { DPAA2_PMD_ERR("Failed to alloc %d flow items", num); return -ENOMEM; @@ -4746,13 +4679,13 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], num = 0; while (pattern[num].type != RTE_FLOW_ITEM_TYPE_END) { - memcpy(&new_pattern[num].generic_item, &pattern[num], - sizeof(struct rte_flow_item)); + rte_memcpy(&new_pattern[num].generic_item, &pattern[num], + sizeof(struct rte_flow_item)); new_pattern[num].in_tunnel = 0; if (pattern[num].type == RTE_FLOW_ITEM_TYPE_VXLAN) tunnel_start = 1; - else if (tunnel_start) + else if (tunnel_start && sp_protocol) new_pattern[num].in_tunnel = 1; num++; } @@ -4789,7 +4722,8 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, if (ret) return ret; - ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern); + ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, + priv->sp_protocol); if (ret) return ret; @@ -5130,7 +5064,8 @@ dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, } static inline int -dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) +dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], + int sp_support) { unsigned int i, j, is_found = 0; int ret = 0; @@ -5154,7 +5089,7 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) } if (is_found) continue; - if (dpaa2_sp_loaded > 0) { + if (sp_support) { for (i = 0; i < sp_supported_num; i++) { if (sp_supported[i] == pattern[j].type) { is_found = 1; @@ -5233,7 +5168,7 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, goto not_valid_params; } /* Verify input pattern list */ - ret = dpaa2_dev_verify_patterns(pattern); + ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol); if (ret < 0) { DPAA2_PMD_ERR("Invalid pattern list is given"); rte_flow_error_set(error, EPERM, diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index f417edf52b..ccb4bbe7dc 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -128,6 +128,16 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; } } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 28/47] drivers: assign dpaa2 Rx CGID per traffic class 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (26 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 27/47] drivers: identify dpaa2 soft parser protocol Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 29/47] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta ` (19 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> RXQs in same TC should use same CGID for congestion set. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 3 +- drivers/net/dpaa2/dpaa2_ethdev.c | 252 ++++++++++++------------ drivers/net/dpaa2/dpaa2_ethdev.h | 3 +- 3 files changed, 126 insertions(+), 132 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f0bc9a3063..12216750a8 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -176,7 +176,6 @@ struct __rte_cache_aligned dpaa2_queue { uint32_t fqid; /*!< Unique ID of this queue */ uint16_t flow_id; /*!< To be used by DPAA2 framework */ uint8_t tc_index; /*!< traffic class identifier */ - uint8_t cgid; /*! < Congestion Group id for this queue */ uint64_t rx_pkts; uint64_t tx_pkts; uint64_t err_pkts; @@ -186,6 +185,8 @@ struct __rte_cache_aligned dpaa2_queue { /**Egress*/ struct qbman_result *cscn; }; + void *cfg; + uint8_t options; struct rte_event ev; dpaa2_queue_cb_dqrr_t *cb; dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index fb1d01e209..0835296ee2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP */ #include <time.h> @@ -682,6 +682,9 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) RTE_MAX_LCORE); dpaa2_queue_storage_free(dpaa2_q, RTE_MAX_LCORE); + if (dpaa2_q->cfg) + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; priv->rx_vq[i] = NULL; } /* cleanup tx queue cscn */ @@ -934,11 +937,12 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, struct fsl_mc_io *dpni = dev->process_private; bool dpcon_allocated = false; struct dpaa2_queue *dpaa2_q; - struct dpni_queue cfg; - uint8_t options = 0; - uint8_t flow_id; + struct dpni_queue *cfg; + struct dpni_taildrop taildrop; + uint8_t qopt = 0; + uint16_t flow_id; uint32_t bpid; - int i, ret; + int ret; PMD_INIT_FUNC_TRACE(); @@ -975,6 +979,10 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } + cfg = rte_zmalloc(NULL, sizeof(struct dpni_queue), 0); + if (!cfg) + return -ENOMEM; + dpaa2_q->cfg = cfg; dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1004,124 +1012,100 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, /*Get the flow id from given VQ id*/ flow_id = dpaa2_q->flow_id; - memset(&cfg, 0, sizeof(struct dpni_queue)); + memset(cfg, 0, sizeof(struct dpni_queue)); - options = options | DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_q); + qopt |= DPNI_QUEUE_OPT_USER_CTX; + cfg->user_context = (size_t)(dpaa2_q); /* napi: schedule the FQ to its DPCON once, when the channel is first * grabbed; never re-bound (the MC refuses scheduled->parked at runtime) */ if (dpcon_allocated) { - options |= DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpaa2_q->napi_dpcon->dpcon_id; - } - - /* check if a private cgr available. */ - for (i = 0; i < priv->max_cgs; i++) { - if (!priv->cgid_in_use[i]) { - priv->cgid_in_use[i] = 1; - break; - } + qopt |= DPNI_QUEUE_OPT_DEST; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpaa2_q->napi_dpcon->dpcon_id; } - if (i < priv->max_cgs) { - options |= DPNI_QUEUE_OPT_SET_CGID; - cfg.cgid = i; - dpaa2_q->cgid = cfg.cgid; + /** RXQs in same TC share same cgid.*/ + if (dpaa2_q->tc_index < priv->max_cgs) { + qopt |= DPNI_QUEUE_OPT_SET_CGID; + cfg->cgid = dpaa2_q->tc_index; + priv->cgid_in_use[dpaa2_q->tc_index]++; } else { - dpaa2_q->cgid = DPAA2_INVALID_CGID; + cfg->cgid = DPAA2_INVALID_CGID; } /*if ls2088 or rev2 device, enable the stashing */ if ((dpaa2_svr_family & 0xffff0000) != SVR_LS2080A) { - options |= DPNI_QUEUE_OPT_FLC; - cfg.flc.stash_control = true; - dpaa2_flc_stashing_clear_all(&cfg.flc.value); + qopt |= DPNI_QUEUE_OPT_FLC; + cfg->flc.stash_control = true; + dpaa2_flc_stashing_clear_all(&cfg->flc.value); if (priv->flags & DPAA2_DATA_STASHING_OFF) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 1; } else { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 0; } if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); } } + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, options, &cfg); + dpaa2_q->tc_index, flow_id, qopt, cfg); if (ret) { + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; DPAA2_PMD_ERR("Error in setting the rx flow: = %d", ret); goto err_free_dpcon; } dpaa2_q->nb_desc = nb_rx_desc; - - if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) { - struct dpni_taildrop taildrop; - + memset(&taildrop, 0, sizeof(struct dpni_taildrop)); + if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) taildrop.enable = 1; - /* Private CGR will use tail drop length as nb_rx_desc. - * for rest cases we can use standard byte based tail drop. - * There is no HW restriction, but number of CGRs are limited, - * hence this restriction is placed. - */ - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - /*enabling per rx queue congestion control */ - taildrop.threshold = nb_rx_desc; - taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; - taildrop.oal = 0; - DPAA2_PMD_DEBUG("Enabling CG Tail Drop on queue = %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - /*enabling per rx queue congestion control */ - taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; - taildrop.units = DPNI_CONGESTION_UNIT_BYTES; - taildrop.oal = CONG_RX_OAL; - DPAA2_PMD_DEBUG("Enabling Byte based Drop on queue= %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, - &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } - } else { /* Disable tail Drop */ - struct dpni_taildrop taildrop = {0}; - DPAA2_PMD_INFO("Tail drop is disabled on queue"); - - taildrop.enable = 0; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } + /* Private CGR will use tail drop length as nb_rx_desc * queues per TC. + * For rest cases we can use standard byte based tail drop. + * There is no HW restriction, but number of CGRs are limited, + * hence this restriction is placed. + */ + if (cfg->cgid != DPAA2_INVALID_CGID && + priv->cgid_in_use[dpaa2_q->tc_index] == 1) { + /*enabling per TC congestion control */ + taildrop.threshold = nb_rx_desc * priv->dist_queues; + taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; + taildrop.oal = 0; + DPAA2_PMD_DEBUG("%s CG Tail Drop on TC%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, + dpaa2_q->tc_index, cfg->cgid, &taildrop); + } else if (cfg->cgid == DPAA2_INVALID_CGID) { + /*enabling per rx queue congestion control */ + taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; + taildrop.units = DPNI_CONGESTION_UNIT_BYTES; + taildrop.oal = CONG_RX_OAL; + DPAA2_PMD_DEBUG("%s Byte based Drop on TC[%d].flow%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index, flow_id); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_QUEUE, DPNI_QUEUE_RX, + dpaa2_q->tc_index, flow_id, &taildrop); } + if (ret) { + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; + DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", ret); + return ret; + } + + dpaa2_q->options = qopt; dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; @@ -1150,8 +1134,8 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct fsl_mc_io *dpni = dev->process_private; struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; - uint8_t options = 0, flow_id; - uint16_t channel_id; + uint8_t qopt = 0; + uint16_t channel_id, flow_id; struct dpni_queue_id qid; uint32_t tc_id; int ret; @@ -1181,7 +1165,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, qopt, &tx_flow_cfg); if (ret) { DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", ret, dev->data->name, tc_id, flow_id); @@ -1190,7 +1174,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, &tx_flow_cfg, &qid); + dpaa2_q->flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1242,12 +1226,12 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; - options = options | DPNI_QUEUE_OPT_USER_CTX; + qopt |= DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, options, &tx_conf_cfg); + flow_id, qopt, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", tc_id, flow_id, ret); @@ -1296,30 +1280,29 @@ dpaa2_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id) struct dpaa2_queue *dpaa2_q = dev->data->rx_queues[rx_queue_id]; struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; struct fsl_mc_io *dpni = priv->eth_dev->process_private; - uint8_t options = 0; + uint8_t qopt = 0; int ret; - struct dpni_queue cfg; + struct dpni_queue *cfg = dpaa2_q->cfg; - memset(&cfg, 0, sizeof(struct dpni_queue)); PMD_INIT_FUNC_TRACE(); total_nb_rx_desc -= dpaa2_q->nb_desc; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - options = DPNI_QUEUE_OPT_CLEAR_CGID; - cfg.cgid = dpaa2_q->cgid; - - ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, dpaa2_q->flow_id, - options, &cfg); - if (ret) - DPAA2_PMD_ERR("Unable to clear CGR from q=%u err=%d", - dpaa2_q->fqid, ret); - priv->cgid_in_use[dpaa2_q->cgid] = 0; - dpaa2_q->cgid = DPAA2_INVALID_CGID; + if (cfg) { + if (cfg->cgid != DPAA2_INVALID_CGID) { + qopt = DPNI_QUEUE_OPT_CLEAR_CGID; + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, + DPNI_QUEUE_RX, dpaa2_q->tc_index, dpaa2_q->flow_id, + qopt, cfg); + if (ret) { + DPAA2_PMD_ERR("Unable to clear CGR from TC[%d].flow%d err=%d", + dpaa2_q->tc_index, dpaa2_q->flow_id, ret); + } + priv->cgid_in_use[cfg->cgid]--; + } + rte_free(cfg); + dpaa2_q->cfg = NULL; } - /* keep the DPCON on the FQ across a reconfigure; freed at dev_close */ if (dpaa2_q->napi_dpcon) dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); @@ -2833,10 +2816,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; + struct dpni_queue *cfg; uint8_t options, priority; int ret; + cfg = dpaa2_ethq->cfg; + if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) dpaa2_ethq->cb = dpaa2_dev_process_parallel_event; else if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) @@ -2849,15 +2834,19 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, priority = (RTE_EVENT_DEV_PRIORITY_LOWEST / queue_conf->ev.priority) * (dpcon->num_priorities - 1); - memset(&cfg, 0, sizeof(struct dpni_queue)); + if (!cfg) { + DPAA2_PMD_ERR("%s: %s-rxq%d was not setup yet!", + __func__, dev->data->name, eth_rx_queue_id); + return -EINVAL; + } options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpcon->dpcon_id; - cfg.destination.priority = priority; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpcon->dpcon_id; + cfg->destination.priority = priority; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) { options |= DPNI_QUEUE_OPT_HOLD_ACTIVE; - cfg.destination.hold_active = 1; + cfg->destination.hold_active = 1; } if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED && @@ -2896,16 +2885,16 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, } options |= DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_ethq); + cfg->user_context = (size_t)(dpaa2_ethq); ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, flow_id, options, cfg); if (ret) { DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); return ret; } - memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); + rte_memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); return 0; } @@ -2917,17 +2906,15 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; - uint8_t options; + struct dpni_queue *cfg; int ret; - memset(&cfg, 0, sizeof(struct dpni_queue)); - options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_NONE; + cfg = dpaa2_ethq->cfg; + cfg->destination.type = DPNI_DEST_NONE; + dpaa2_ethq->options &= ~DPNI_QUEUE_OPT_DEST; ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, dpaa2_ethq->flow_id, dpaa2_ethq->options, cfg); if (ret) DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); @@ -3547,10 +3534,15 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ - if (attr.options & DPNI_OPT_CUSTOM_CG) + if (attr.options & DPNI_OPT_CUSTOM_CG) { priv->max_cgs = attr.num_cgs; - else + if (priv->max_cgs < priv->num_rx_tc) { + DPAA2_PMD_WARN("DPNI%d has no enough cgids(%d) to set %d TCs", + hw_id, priv->max_cgs, priv->num_rx_tc); + } + } else { priv->max_cgs = 0; + } for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 9c52a6c248..65c5378547 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -478,7 +478,8 @@ struct dpaa2_dev_priv { uint8_t en_ordered; uint8_t en_loose_ordered; uint8_t max_cgs; - uint8_t cgid_in_use[MAX_RX_QUEUES]; + /** RXQs in same TC share same cgid.*/ + uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; /* Lowest priority FS flow id to receive flow steering miss frames. */ uint16_t default_flow; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 29/47] drivers: inherit dpaa2 rxq config for event queue 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (27 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 28/47] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 30/47] net/dpaa2: rename Rx queue flags Prashant Gupta ` (18 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The configuration parameter in event queue attachment should use flc and cgid configured in rxq setup. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 2 +- drivers/net/dpaa2/dpaa2_ethdev.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 12216750a8..f87bf51d09 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2025 NXP * */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0835296ee2..57c6e8e90b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -2815,11 +2815,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; + uint8_t flow_id; struct dpni_queue *cfg; uint8_t options, priority; int ret; + flow_id = dpaa2_ethq->flow_id; cfg = dpaa2_ethq->cfg; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 30/47] net/dpaa2: rename Rx queue flags 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (28 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 29/47] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 31/47] drivers: rework dpaa2 Tx confirmation Prashant Gupta ` (17 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change; it prepares the flag namespace for the Tx confirmation rework that follows. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 4 ++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 57c6e8e90b..15a886b3e8 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -547,7 +547,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, qopt |= DPNI_QUEUE_OPT_FLC; cfg->flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg->flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg->flc.value); dpaa2_q->data_stashing_off = 1; @@ -1499,7 +1499,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3462,7 +3462,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3592,7 +3592,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 65c5378547..bdd8855023 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,9 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index ccb4bbe7dc..a03e3fd8db 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -870,7 +870,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1142,7 +1142,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 31/47] drivers: rework dpaa2 Tx confirmation 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (29 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 30/47] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 32/47] net/dpaa2: ptp enhancements Prashant Gupta ` (16 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Mbufs released by Tx confirmation may come from any mempool, so use the RTE mbuf free API instead of returning the buffers directly to the bman pool. The FD FLC field now carries the Tx mbuf pointer so that the confirmation callback can release it to either the platform pool or an external pool. Absolute and dynamic Tx confirmation become independent settings, giving three Tx modes: 1) No confirmation (default). Suited to traffic that is mostly sent from the platform pool. For the few packets from other pools the driver allocates a platform buffer, copies the data and frees the original. 2) Absolute confirmation. Suited to traffic mostly sent from non platform pools. Every Tx packet raises a confirmation, configured at queue setup, and the callback frees the packet. 3) Dynamic confirmation. Confirmation is raised only for packets from non platform pools; the driver marks each packet accordingly at runtime. This suits a roughly even mix of platform and non platform buffers. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 2 +- drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 63 +- drivers/net/dpaa2/dpaa2_ethdev.h | 39 +- drivers/net/dpaa2/dpaa2_ptp.c | 4 +- drivers/net/dpaa2/dpaa2_rxtx.c | 1501 ++++++++---------- 7 files changed, 742 insertions(+), 874 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f87bf51d09..b3aad85d06 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -198,6 +198,7 @@ struct __rte_cache_aligned dpaa2_queue { uint16_t tm_sw_td; /*!< TM software taildrop */ uint64_t offloads; uint64_t lpbk_cntx; + int32_t ts_to_cnfd; uint8_t data_stashing_off; /* NAPI rx-interrupt: per-queue DPCON bound to this FQ at dev_start * (DEST_DPCON, static); the polling worker points the channel's CDAN at diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c index 26ad105c73..fee96b3529 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c @@ -484,7 +484,7 @@ dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, */ /* ... rx buffer layout ... */ - if (priv->flags & DPAA2_TX_DYNAMIC_CONF_ENABLE) { + if (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) { int out_min_hdr_room, in_min_hdr_room; /** Additional headroom layout for IPSec with TX configure * dynamic enabled. diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h index a670098958..b06fa3f644 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019,2022,2024 NXP + * Copyright 2016,2019,2022,2024-2026 NXP * */ @@ -281,6 +281,10 @@ struct dpaa2_faead { /*UPD (Update prepended data)*/ #define DPAA2_ANNOT_FAEAD_UPD 0x00000010 +#define DPAA2_TX_CONFIRM_ENABLE \ + (DPAA2_ANNOT_FAEAD_A4V | DPAA2_ANNOT_FAEAD_EBDD | \ + DPAA2_ANNOT_FAEAD_EBDDV) + /* Debug frame, otherwise supposed to be discarded */ #define DPAA2_ETH_FAS_DISC 0x80000000 /* MACSEC frame */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 15a886b3e8..61b7ae138c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -34,6 +34,8 @@ #define DRIVER_LOOPBACK_MODE "drv_loopback" #define DRIVER_NO_PREFETCH_MODE "drv_no_prefetch" #define DRIVER_TX_CONF "drv_tx_conf" +#define DRIVER_TX_DYNAMIC_CONF "drv_tx_dyn_conf" +#define DRIVER_TX_DYNAMIC_CONF_PREFETCH "drv_tx_dyn_conf_pre" #define DRIVER_RX_PARSE_ERR_DROP "drv_rx_parse_drop" #define DRIVER_ERROR_QUEUE "drv_err_queue" #define DRIVER_NO_TAILDROP "drv_no_taildrop" @@ -522,7 +524,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (priv->flags & DPAA2_TX_CONF_ENABLE) + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else tot_queues = priv->nb_rx_queues + priv->nb_tx_queues; @@ -578,7 +580,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; @@ -693,7 +695,7 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) rte_free(dpaa2_q->cscn); priv->tx_vq[i] = NULL; } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /* cleanup tx conf queue storage */ for (i = 0; i < priv->nb_tx_queues; i++) { dpaa2_q = priv->tx_conf_vq[i]; @@ -1143,6 +1145,13 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, PMD_INIT_FUNC_TRACE(); + /* Tx deferred start is not supported */ + if (tx_conf->tx_deferred_start) { + DPAA2_PMD_ERR("%s:Tx deferred start not supported", + dev->data->name); + return -EINVAL; + } + dpaa2_q->nb_desc = UINT16_MAX; dpaa2_q->offloads = tx_conf->offloads; @@ -1222,7 +1231,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->cb_eqresp_free = dpaa2_dev_free_eqresp_buf; dev->data->tx_queues[tx_queue_id] = dpaa2_q; - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; @@ -3585,10 +3594,22 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) DPAA2_PMD_INFO("DPDK IEEE1588 is enabled"); priv->flags |= DPAA2_TX_CONF_ENABLE; #endif + priv->tx_conf_type = DPAA2_TX_NO_CONF; + /* Used with ``fslmc:dpni.1,drv_tx_conf=1`` */ if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_CONF)) { - priv->flags |= DPAA2_TX_CONF_ENABLE; - DPAA2_PMD_INFO("TX_CONF Enabled"); + priv->tx_conf_type = DPAA2_TX_ABSOLUTE_CONF; + DPAA2_PMD_INFO("TX_ABSOLUTE_CONF Enabled"); + } else if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_DYNAMIC_CONF)) { + priv->tx_conf_type = DPAA2_TX_DYNAMIC_CONF; + DPAA2_PMD_INFO("TX_DYNAMIC_CONF Enabled"); + priv->flags |= DPAA2_TX_PREFETCH_DYNAMIC_CONF; + if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_DYNAMIC_CONF_PREFETCH)) + priv->flags &= ~DPAA2_TX_PREFETCH_DYNAMIC_CONF; + + DPAA2_PMD_INFO("Tx dynamic prefetch confirm %s", + (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) ? + "enabled" : "disabled"); } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { @@ -3603,7 +3624,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); @@ -3614,7 +3635,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->num_channels; i++) { /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) { ret = dpni_set_tx_confirmation_mode(dpni_dev, CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); } else { @@ -3651,34 +3672,22 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) /* ... tx buffer layout ... */ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | - DPNI_BUF_LAYOUT_OPT_TIMESTAMP; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; layout.pass_timestamp = true; - } else { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; } + layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, &layout); + DPNI_QUEUE_TX, &layout); if (ret) { DPAA2_PMD_ERR("Error (%d) in setting tx buffer layout", ret); goto init_err; } - - /* ... tx-conf and error buffer layout ... */ - memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; - layout.pass_timestamp = true; - } - layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; - layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX_CONFIRM, &layout); + DPNI_QUEUE_TX_CONFIRM, &layout); if (ret) { - DPAA2_PMD_ERR("Error (%d) in setting tx-conf buffer layout", - ret); + DPAA2_PMD_ERR("Error (%d) in setting tx conf buffer layout", ret); goto init_err; } @@ -3979,6 +3988,8 @@ RTE_PMD_REGISTER_PARAM_STRING(NET_DPAA2_PMD_DRIVER_NAME, DRIVER_LOOPBACK_MODE "=<int> " DRIVER_NO_PREFETCH_MODE "=<int>" DRIVER_TX_CONF "=<int>" + DRIVER_TX_DYNAMIC_CONF "=<int>" + DRIVER_TX_DYNAMIC_CONF_PREFETCH "=<int>" DRIVER_RX_PARSE_ERR_DROP "=<int>" DRIVER_ERROR_QUEUE "=<int>" DRIVER_NO_TAILDROP "=<int>" diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index bdd8855023..c9b7a8ae17 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -91,18 +91,14 @@ #define DPAA2_TX_DPNI_LOOPBACK_MODE RTE_BIT32(7) -/* Tx confirmation enabled */ -#define DPAA2_TX_CONF_ENABLE RTE_BIT32(8) +#define DPAA2_TX_PREFETCH_DYNAMIC_CONF RTE_BIT32(8) -/* Tx dynamic confirmation enabled, - * only valid with Tx confirmation enabled. - */ -#define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(9) + +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -/* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) +#define DPAA2_RX_SCHED_STRICT_ORDER_FLAG RTE_BIT32(11) -#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ @@ -451,6 +447,12 @@ struct dpaa2_dev_meter { uint32_t policy_id; }; +enum dpaa2_tx_conf_type { + DPAA2_TX_NO_CONF, + DPAA2_TX_ABSOLUTE_CONF, + DPAA2_TX_DYNAMIC_CONF +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -466,6 +468,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + enum dpaa2_tx_conf_type tx_conf_type; int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; @@ -504,16 +507,16 @@ struct dpaa2_dev_priv { uint64_t ss_iova; uint64_t ss_param_iova; /*stores timestamp of last received packet on dev*/ - uint64_t rx_timestamp; + RTE_ATOMIC(uint64_t) rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ - uint64_t tx_timestamp; + RTE_ATOMIC(uint64_t) tx_timestamp; int rx_ts_offset; uint64_t rx_ts_flag; - /* stores pointer to next tx_conf queue that should be processed, + /* stores next tx queue to be confirmed that should be processed, * it corresponds to last packet transmitted */ - struct dpaa2_queue *next_tx_conf_queue; + struct dpaa2_queue * RTE_ATOMIC(next_txq_to_cnf); struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; @@ -646,7 +649,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); -uint16_t dpaa2_dev_tx_conf(void *queue) __rte_unused; +uint16_t dpaa2_dev_tx_conf(void *txq, int drain); int dpaa2_timesync_enable(struct rte_eth_dev *dev); int dpaa2_timesync_disable(struct rte_eth_dev *dev); @@ -663,6 +666,14 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); + +__rte_internal +struct rte_mbuf *__rte_hot +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); +__rte_internal +struct rte_mbuf *__rte_hot +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); + int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index 751e558c73..c845291c68 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -111,9 +111,9 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; - if (priv->next_tx_conf_queue) { + if (priv->next_txq_to_cnf) { while (!priv->tx_timestamp) - dpaa2_dev_tx_conf(priv->next_tx_conf_queue); + dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); } else { return -1; } diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index a03e3fd8db..3212790957 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2026 NXP * */ @@ -75,6 +75,16 @@ dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, DPAA2_RESET_FD_FLC(_fd); \ } while (0) +#define DPAA2_MBUF_TO_CONF_CONTIG_FD(_mbuf, _fd) do { \ + DPAA2_SET_FD_ADDR(_fd, DPAA2_MBUF_VADDR_TO_IOVA(_mbuf)); \ + DPAA2_SET_FD_LEN(_fd, (_mbuf)->data_len); \ + DPAA2_SET_ONLY_FD_BPID(_fd, MAX_BPID); \ + DPAA2_SET_FD_IVP(_fd); \ + DPAA2_SET_FD_OFFSET(_fd, (_mbuf)->data_off); \ + DPAA2_SET_FD_FRC(_fd, 0); \ + DPAA2_RESET_FD_CTRL(_fd); \ + DPAA2_SET_FD_FLC(_fd, _mbuf); \ +} while (0) static inline void dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, @@ -98,7 +108,6 @@ dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, m->hash.rss); } } - static void __rte_hot dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, struct rte_mbuf *m, const struct qbman_fd *fd, @@ -237,13 +246,6 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, "(4)=0x%" PRIx64 "\t", annotation->word3, annotation->word4); -#if defined(RTE_LIBRTE_IEEE1588) - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) { - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST; - } -#endif - if (BIT_ISSET_AT_POS(annotation->word3, L2_VLAN_1_PRESENT)) { vlan_tci = rte_pktmbuf_mtod_offset(mbuf, uint16_t *, (VLAN_TCI_OFFSET_1(annotation->word5) >> 16)); @@ -367,13 +369,14 @@ dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, return dpaa2_dev_rx_parse_slow(mbuf, annotation); } -static inline struct rte_mbuf *__rte_hot +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_sg_fd_to_mbuf) +struct rte_mbuf *__rte_hot dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; - size_t sg_addr, fd_addr; + size_t fd_addr; int i = 0; - void *hw_annot_addr; + void *hw_annot_addr, *sg_addr; struct rte_mbuf *first_seg, *next_seg, *cur_seg, *temp; fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); @@ -383,7 +386,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) sgt = (struct qbman_sge *)(fd_addr + DPAA2_GET_FD_OFFSET(fd)); sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); /* First Scatter gather entry */ first_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, @@ -413,8 +416,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) cur_seg = first_seg; while (!DPAA2_SG_IS_FINAL(sge) && i < DPAA2_MAX_SGS) { sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR( - DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); next_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, rte_dpaa2_bpid_info[DPAA2_GET_FLE_BPID(sge)].meta_data_size); next_seg->buf_addr = (uint8_t *)sg_addr; @@ -442,7 +444,8 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return (void *)first_seg; } -static inline struct rte_mbuf *__rte_hot +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_fd_to_mbuf) +struct rte_mbuf *__rte_hot dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); @@ -499,119 +502,295 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return mbuf; } +static void dpaa2_dev_tx_enable_tstamp(struct qbman_fd *fd) +{ + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + + /* Set frame annotation status field as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FASV; + + /* Set frame annotation egress action descriptor as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; + + /* Set Annotation Length as 128B */ + (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD); +} + +static inline struct rte_mbuf * +dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) +{ + struct rte_mbuf *mc = rte_pktmbuf_alloc(mp); + + if (!mc) + return NULL; + if ((mc->data_off + sgm->data_len) > mc->buf_len) { + rte_pktmbuf_free(mc); + return NULL; + } + rte_memcpy(rte_pktmbuf_mtod(mc, void *), + rte_pktmbuf_mtod(sgm, void *), sgm->data_len); + mc->pkt_len = sgm->data_len; + mc->data_len = sgm->data_len; + mc->next = NULL; + + return mc; +} + +static inline void +dpaa2_dev_tx_config_dynamic_confirm(struct qbman_fd *fd, + struct dpaa2_queue *txq, int enable, int tstamp) +{ + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + + if (tstamp) { + DPAA2_SET_FD_FRC(fd, + DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV | DPAA2_FD_FRC_FASV); + fd->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + } else { + DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV); + } + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + if (enable) { + fd_faead->fqid = txq->tx_conf_queue->fqid; + fd_faead->ctrl = DPAA2_TX_CONFIRM_ENABLE; + if (tstamp) { + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | + DPAA2_ANNOT_FAEAD_UPD); + } + } else { + fd_faead->fqid = 0; + fd_faead->ctrl &= (~DPAA2_TX_CONFIRM_ENABLE); + } +} + +static int +dpaa2_dev_tx_no_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf, + struct rte_mempool *hw_mp) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg, *mi, *prev, *copy_mbuf; + + cur_seg = mbuf; + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + mi = rte_mbuf_from_indirect(cur_seg); + if (rte_mbuf_refcnt_read(mi) > 1) + rte_mbuf_refcnt_update(mi, -1); + else + rte_pktmbuf_free_seg(mi); + copy_mbuf->next = cur_seg->next; + if (prev) + prev->next = copy_mbuf; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + if (unlikely(RTE_MBUF_HAS_EXTBUF(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index)) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + + copy_mbuf->next = cur_seg->next; + + if (prev) + prev->next = copy_mbuf; + if (rte_mbuf_refcnt_read(cur_seg) > 1) + rte_mbuf_refcnt_update(cur_seg, -1); + else + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + if (unlikely(rte_mbuf_refcnt_read(cur_seg) > 1)) { + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + rte_mbuf_refcnt_update(cur_seg, -1); + } else { + DPAA2_SET_FLE_BPID(sge, mempool_to_bpid(cur_seg->pool)); + } + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); + + return 0; +} + +static void +dpaa2_dev_tx_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg = mbuf, *mi, *prev; + + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + mi = rte_mbuf_from_indirect(cur_seg); + mi->next = cur_seg->next; + if (prev) + prev->next = mi; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = mi; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); +} + static int __rte_noinline __rte_hot -eth_mbuf_to_sg_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *free_buf, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf, int tstamp) { - struct rte_mbuf *cur_seg = mbuf, *mi, *temp; - struct qbman_sge *sgt, *sge = NULL; - int i, offset = 0; + struct rte_mbuf *cur_seg = mbuf, *sg_mbuf; + struct qbman_sge *sgt; + int offset = 0, ret, need_dyconf = false, need_conf = false; + uint16_t nb_segs = mbuf->nb_segs; + uint32_t sg_size = nb_segs * sizeof(struct qbman_sge); + struct rte_mempool *mp; -#ifdef RTE_LIBRTE_IEEE1588 - /* annotation area for timestamp in first buffer */ - offset = 0x64; -#endif - if (RTE_MBUF_DIRECT(mbuf) && - (mbuf->data_off > (mbuf->nb_segs * sizeof(struct qbman_sge) - + offset))) { - temp = mbuf; - if (rte_mbuf_refcnt_read(temp) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - fd->simple.bpid_offset = 0; + if (conf == DPAA2_TX_DYNAMIC_CONF) { + while (cur_seg) { + if (!RTE_MBUF_DIRECT(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index || + rte_mbuf_refcnt_read(cur_seg) > 1 || tstamp) { + need_dyconf = true; + break; + } + cur_seg = cur_seg->next; + } + cur_seg = mbuf; + } + if (need_dyconf || conf == DPAA2_TX_ABSOLUTE_CONF) + need_conf = true; + + if (need_dyconf || tstamp) + offset = DPAA2_FD_PTA_SIZE + DPAA2_DYN_TX_MIN_FD_OFFSET; + + if (mbuf->pool->ops_index == hw_mp->ops_index && + RTE_MBUF_DIRECT(mbuf) && + (mbuf->data_off > RTE_ALIGN(sg_size + offset, 8))) { + sg_mbuf = mbuf; + mp = mbuf->pool; + if (need_conf) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); DPAA2_SET_FD_IVP(fd); - rte_mbuf_refcnt_update(temp, -1); } else { - DPAA2_SET_ONLY_FD_BPID(fd, bpid); + if (unlikely(rte_mbuf_refcnt_read(sg_mbuf) > 1)) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + rte_mbuf_refcnt_update(sg_mbuf, -1); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(mp)); + } + } #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif - } DPAA2_SET_FD_OFFSET(fd, offset); } else { - temp = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); - if (temp == NULL) { + sg_mbuf = NULL; + if (dpaa2_tx_sg_pool) + sg_mbuf = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); + if (!sg_mbuf) { DPAA2_PMD_DP_DEBUG("No memory to allocate S/G table"); return -ENOMEM; } - DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); - DPAA2_SET_FD_OFFSET(fd, temp->data_off); + if (need_conf) { + if (need_dyconf) + sg_mbuf->data_off = RTE_ALIGN(offset, 8); + else + sg_mbuf->data_off = RTE_PKTMBUF_HEADROOM; + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); + } + DPAA2_SET_FD_OFFSET(fd, sg_mbuf->data_off); + offset = sg_mbuf->data_off; #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif } - DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(temp)); + + /*Set Scatter gather table and Scatter gather entries*/ + sgt = (void *)((size_t)sg_mbuf->buf_addr + offset); + DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(sg_mbuf)); DPAA2_SET_FD_LEN(fd, mbuf->pkt_len); DPAA2_FD_SET_FORMAT(fd, qbman_fd_sg); DPAA2_RESET_FD_FRC(fd); DPAA2_RESET_FD_CTRL(fd); - DPAA2_RESET_FD_FLC(fd); - /*Set Scatter gather table and Scatter gather entries*/ - sgt = (struct qbman_sge *)( - (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) - + DPAA2_GET_FD_OFFSET(fd)); + if (need_conf) + DPAA2_SET_FD_FLC(fd, sg_mbuf); + else + DPAA2_RESET_FD_FLC(fd); + if (need_dyconf) + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); + else if (tstamp) + dpaa2_dev_tx_enable_tstamp(fd); - for (i = 0; i < mbuf->nb_segs; i++) { - sge = &sgt[i]; - /*Resetting the buffer pool id and offset field*/ - sge->fin_bpid_offset = 0; - DPAA2_SET_FLE_ADDR(sge, rte_pktmbuf_iova(cur_seg)); - sge->length = cur_seg->data_len; - if (RTE_MBUF_DIRECT(cur_seg)) { - /* if we are using inline SGT in same buffers - * set the FLE FMT as Frame Data Section - */ - if (temp == cur_seg) { - DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); - DPAA2_SET_FLE_IVP(sge); - } else { - if (rte_mbuf_refcnt_read(cur_seg) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - rte_mbuf_refcnt_update(cur_seg, -1); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(cur_seg->pool)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)cur_seg), - (void **)&cur_seg, 1, 0); -#endif - } - } - } else if (RTE_MBUF_HAS_EXTBUF(cur_seg)) { - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FLE_IVP(sge); - } else { - /* Get owner MBUF from indirect buffer */ - mi = rte_mbuf_from_indirect(cur_seg); - if (rte_mbuf_refcnt_read(mi) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * owner buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(mi->pool)); - rte_mbuf_refcnt_update(mi, 1); - } - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - } - cur_seg = cur_seg->next; + if (cur_seg != sg_mbuf && need_conf) + sg_mbuf->next = cur_seg; + + if (need_conf) { + dpaa2_dev_tx_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, sg_mbuf); + } else { + ret = dpaa2_dev_tx_no_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, + sg_mbuf, hw_mp); + if (ret) + return ret; } - DPAA2_SG_SET_FINAL(sge, true); + if (dy_conf && need_dyconf) + *dy_conf = true; + return 0; } @@ -632,101 +811,59 @@ dpaa2_dev_prefetch_next_psr(const struct qbman_result *dq) rte_prefetch0(&annotation->word3); } -static void -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) __rte_unused; - -static void __rte_noinline __rte_hot -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +static int __rte_noinline __rte_hot +dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf, int tstamp) { - DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, bpid); + int need_dyconf = false, need_conf = false; + struct rte_mbuf *mi; + struct rte_mbuf *copy_mbuf; + int ret = 0; - DPAA2_PMD_DP_DEBUG("mbuf =%p, mbuf->buf_addr =%p, off = %d," - "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", - mbuf, mbuf->buf_addr, mbuf->data_off, - DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd)); - if (RTE_MBUF_DIRECT(mbuf)) { + if (unlikely(RTE_MBUF_CLONED(mbuf))) { + mi = rte_mbuf_from_indirect(mbuf); if (rte_mbuf_refcnt_read(mbuf) > 1) { - DPAA2_SET_FD_IVP(fd); rte_mbuf_refcnt_update(mbuf, -1); + } else { + rte_pktmbuf_init(mbuf->pool, NULL, mbuf, 0); + rte_pktmbuf_free(mbuf); } -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - else - rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf), - (void **)&mbuf, 1, 0); -#endif - } else if (RTE_MBUF_HAS_EXTBUF(mbuf)) { - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FD_IVP(fd); + mbuf = mi; + } + if (conf == DPAA2_TX_DYNAMIC_CONF && + (mbuf->pool->ops_index != hw_mp->ops_index || + RTE_MBUF_HAS_EXTBUF(mbuf) || + rte_mbuf_refcnt_read(mbuf) > 1 || tstamp)) + need_dyconf = true; + if (conf == DPAA2_TX_ABSOLUTE_CONF || need_dyconf) + need_conf = true; + + if (need_conf) { + DPAA2_MBUF_TO_CONF_CONTIG_FD(mbuf, fd); + } else if (mbuf->pool->ops_index == hw_mp->ops_index) { + DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, mempool_to_bpid(mbuf->pool)); } else { - struct rte_mbuf *mi; - - mi = rte_mbuf_from_indirect(mbuf); - if (rte_mbuf_refcnt_read(mi) > 1) - DPAA2_SET_FD_IVP(fd); - else - rte_mbuf_refcnt_update(mi, 1); - - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(mbuf, hw_mp); + if (!copy_mbuf) { + ret = -ENOMEM; + goto quit; + } + DPAA2_MBUF_TO_CONTIG_FD(copy_mbuf, fd, mempool_to_bpid(hw_mp)); +quit: + rte_pktmbuf_free(mbuf); } -} -static inline int __rte_hot -eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, uint16_t bpid) -{ - struct rte_mbuf *m; - void *mb = NULL; - - if (rte_dpaa2_mbuf_alloc_bulk( - rte_dpaa2_bpid_info[bpid].bp_list->mp, &mb, 1)) { - DPAA2_PMD_DP_DEBUG("Unable to allocated DPAA2 buffer"); - return -1; + if (need_dyconf) { + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); + if (dy_conf) + *dy_conf = true; + } else if (tstamp) { + dpaa2_dev_tx_enable_tstamp(fd); } - m = (struct rte_mbuf *)mb; - memcpy((char *)m->buf_addr + mbuf->data_off, - (void *)((char *)mbuf->buf_addr + mbuf->data_off), - mbuf->pkt_len); - - /* Copy required fields */ - m->data_off = mbuf->data_off; - m->ol_flags = mbuf->ol_flags; - m->packet_type = mbuf->packet_type; - m->tx_offload = mbuf->tx_offload; - DPAA2_MBUF_TO_CONTIG_FD(m, fd, bpid); - -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)m), - (void **)&m, 1, 0); -#endif - DPAA2_PMD_DP_DEBUG( - "mbuf: %p, BMAN buf addr: %p, fdaddr: %" PRIx64 ", bpid: %d," - " meta: %d, off: %d, len: %d", - (void *)mbuf, - mbuf->buf_addr, - DPAA2_GET_FD_ADDR(fd), - DPAA2_GET_FD_BPID(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_OFFSET(fd), - DPAA2_GET_FD_LEN(fd)); - -return 0; + return ret; } static void @@ -812,7 +949,6 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) dpaa2_dev_rx_parse_offset(priv, mbuf, fd); dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); - DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd), @@ -1237,12 +1373,6 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1273,150 +1403,208 @@ dpaa2_dev_rx_channel(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) return dpaa2_dev_rx_common(queue, bufs, nb_pkts, true); } -uint16_t dpaa2_dev_tx_conf(void *queue) +static inline int +dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, + struct rte_mbuf *mbuf) { - /* Function receive frames for a given device and VQ */ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct qbman_result *dq_storage; + while (mbuf) { + if (mbuf->pool != mp) + return false; + mbuf = mbuf->next; + } + + return true; +} + +uint16_t dpaa2_dev_tx_conf(void *txq, int drain) +{ + /* Function receive frames for a given device and VQ*/ + struct dpaa2_queue *dpaa2_txq = txq; + struct dpaa2_queue *dpaa2_q = dpaa2_txq->tx_conf_queue; + struct qbman_result *dq_storage, *dq_storage1 = NULL; uint32_t fqid = dpaa2_q->fqid; - int ret, num_tx_conf = 0; - uint8_t pending, status, num_pulled; + int ret, pull_size, total = 0, bulk_free; + uint8_t pending, status, idx, buf_idx; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; - struct qbman_release_desc releasedesc; - uint32_t bpid; - uint64_t buf; -#if defined(RTE_LIBRTE_IEEE1588) - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_annot_hdr *annotation; - void *v_addr; - struct rte_mbuf *mbuf; -#endif + struct queue_storage_info_t *q_storage; + struct qbman_result *rst; - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); + struct rte_mbuf *mbufs[dpaa2_dqrr_size]; + struct rte_mempool *mp = NULL; + #define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + +conf_again: + bulk_free = true; + idx = 0; + q_storage = dpaa2_q->q_storage[rte_lcore_id()]; + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); + DPAA2_PMD_ERR("Failure in affining portal"); return 0; } } - swp = DPAA2_PER_LCORE_PORTAL; - do { - dq_storage = dpaa2_q->q_storage[0]->dq_storage[0]; + swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + pull_size = dpaa2_dqrr_size; + if (unlikely(!q_storage->active_dqs)) { + q_storage->toggle = 0; + dq_storage = q_storage->dq_storage[q_storage->toggle]; + q_storage->last_num_pkts = pull_size; qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, + q_storage->last_num_pkts); qbman_pull_desc_set_fq(&pulldesc, fqid); qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - - qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size); - + DPAA2_VADDR_TO_IOVA(dq_storage), 1); + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } while (1) { if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued." - "QBMAN is busy"); + DPAA2_PMD_DP_DEBUG("QBMAN is busy (1)"); /* Portal was busy, try again */ continue; } break; } + q_storage->active_dqs = dq_storage; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage); + } - rte_prefetch0((void *)((size_t)(dq_storage + 1))); - /* Check if the previous issued command is completed. */ - while (!qbman_check_command_complete(dq_storage)) - ; - - num_pulled = 0; - pending = 1; - do { - /* Loop until the dq_storage is updated with - * new token by QBMAN - */ - while (!qbman_check_new_result(dq_storage)) - ; - rte_prefetch0((void *)((size_t)(dq_storage + 2))); - /* Check whether Last Pull command is Expired and - * setting Condition for Loop termination - */ - if (qbman_result_DQ_is_pull_complete(dq_storage)) { - pending = 0; - /* Check for valid frame. */ - status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & - QBMAN_DQ_STAT_VALIDFRAME) == 0)) - continue; - } - if (dpaa2_svr_family != SVR_LX2160A) - /** Packet type is parsed from FRC for LX2160A.*/ - dpaa2_dev_prefetch_next_psr(dq_storage); + dq_storage = q_storage->active_dqs; + rte_prefetch0((void *)(dq_storage)); + rte_prefetch0((void *)(dq_storage + 1)); - fd = qbman_result_DQ_fd(dq_storage); - bpid = DPAA2_GET_FD_BPID(fd); + /* Prepare next pull descriptor. This will give space for the + * prefetching done on DQRR entries + */ + q_storage->toggle ^= 1; + dq_storage1 = q_storage->dq_storage[q_storage->toggle]; + qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, pull_size); + qbman_pull_desc_set_fq(&pulldesc, fqid); + qbman_pull_desc_set_storage(&pulldesc, dq_storage1, + DPAA2_VADDR_TO_IOVA(dq_storage1), 1); - /* Create a release descriptor required for releasing - * buffers into QBMAN - */ - qbman_release_desc_clear(&releasedesc); - qbman_release_desc_set_bpid(&releasedesc, bpid); + /* Check if the previous issued command is completed. + * Also seems like the SWP is shared between the Ethernet Driver + * and the SEC driver. + */ + while (!qbman_check_command_complete(dq_storage)) + ; + if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id)) + clear_swp_active_dqs(q_storage->active_dpio_id); - buf = DPAA2_GET_FD_ADDR(fd); - /* feed them to bman */ - do { - ret = qbman_swp_release(swp, &releasedesc, - &buf, 1); - } while (ret == -EBUSY); + pending = 1; - dq_storage++; - num_tx_conf++; - num_pulled++; -#if defined(RTE_LIBRTE_IEEE1588) - v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); - mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); - - if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - annotation = (struct dpaa2_annot_hdr *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE); - priv->tx_timestamp = annotation->word2; - } -#endif - } while (pending); + do { + /* Loop until the dq_storage is updated with + * new token by QBMAN + */ + while (!qbman_check_new_result(dq_storage)) + ; + rte_prefetch0((void *)(dq_storage + 2)); + /* Check whether Last Pull command is Expired and + * setting Condition for Loop termination + */ + if (qbman_result_DQ_is_pull_complete(dq_storage)) { + pending = 0; + /* Check for valid frame. */ + status = qbman_result_DQ_flags(dq_storage); + if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) + continue; + } - /* Last VDQ provided all packets and more packets are requested */ - } while (num_pulled == dpaa2_dqrr_size); + fd = qbman_result_DQ_fd(dq_storage); + mbufs[idx] = (void *)(uintptr_t)DPAA2_GET_FD_FLC(fd); + if (unlikely(!mp)) + mp = mbufs[idx]->pool; + if (unlikely(rte_mbuf_refcnt_read(mbufs[idx]) > 1)) + bulk_free = false; + if (bulk_free == true && + !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) + bulk_free = false; + idx++; + dq_storage++; + if (idx >= dpaa2_dqrr_size) + break; + } while (pending); - dpaa2_q->rx_pkts += num_tx_conf; + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } + /* issue a volatile dequeue command for next pull */ + while (1) { + if (qbman_swp_pull(swp, &pulldesc)) { + DPAA2_PMD_DP_DEBUG("QBMAN is busy (2)"); + continue; + } + break; + } + q_storage->active_dqs = dq_storage1; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage1); - return num_tx_conf; -} -#ifdef RTE_LIBRTE_IEEE1588 -/* Configure the egress frame annotation for timestamp update */ -static void enable_tx_tstamp(struct qbman_fd *fd) -{ - struct dpaa2_faead *fd_faead; + if (bulk_free) { + rte_pktmbuf_free_bulk(mbufs, idx); + } else { + for (buf_idx = 0; buf_idx < idx; buf_idx++) { + if (rte_mbuf_refcnt_read(mbufs[buf_idx]) > 1) + rte_mbuf_refcnt_update(mbufs[buf_idx], -1); + else + rte_pktmbuf_free(mbufs[buf_idx]); + } + } - /* Set frame annotation status field as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FASV; + dpaa2_q->rx_pkts += idx; + total += idx; + if (drain && pending) + goto conf_again; - /* Set frame annotation egress action descriptor as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; + return total; +} - /* Set Annotation Length as 128B */ - (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; +static inline int +dpaa2_dev_tx_fast_mbuf_to_fd(struct rte_eth_dev_data *dev, + struct rte_mbuf *buf, struct qbman_fd *fd, + enum dpaa2_tx_conf_type conf) +{ + struct rte_mempool *mp = buf->pool; + struct dpaa2_dev_priv *priv = dev->dev_private; + + if (likely(RTE_MBUF_DIRECT(buf) && + mp && mp->ops_index == + priv->bp_list->dpaa2_ops_index && + buf->nb_segs == 1 && + rte_mbuf_refcnt_read(buf) == 1)) { + if (unlikely(buf->next)) { + DPAA2_PMD_WARN("Single mbuf has next segment(%p)", + buf->next); + } + if (unlikely(conf == DPAA2_TX_ABSOLUTE_CONF)) + DPAA2_MBUF_TO_CONF_CONTIG_FD(buf, fd); + else + DPAA2_MBUF_TO_CONTIG_FD(buf, fd, mempool_to_bpid(mp)); +#ifdef RTE_LIBRTE_MEMPOOL_DEBUG + rte_mempool_check_cookies(rte_mempool_from_obj(buf), + (void **)&buf, 1, 0); +#endif + return 0; + } - /* enable update of confirmation frame annotation */ - fd_faead = (struct dpaa2_faead *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); - fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | - DPAA2_ANNOT_FAEAD_UPD; + return -EAGAIN; } -#endif + /* * Callback to handle sending packets through WRIOP based interface */ @@ -1424,28 +1612,24 @@ uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ - uint32_t loop, retry_count; - int32_t ret; + uint32_t loop, retry_count, i; + int32_t ret, tstamp[MAX_TX_RING_SLOTS]; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; uint32_t frames_to_send; - struct rte_mempool *mp; struct qbman_eq_desc eqdesc; - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; + struct dpaa2_queue *dpaa2_q = queue; struct qbman_swp *swp; uint16_t num_tx = 0; - uint16_t bpid; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct rte_mempool *hw_mp; uint32_t flags[MAX_TX_RING_SLOTS] = {0}; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } @@ -1453,19 +1637,17 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) swp = DPAA2_PER_LCORE_PORTAL; DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); + eth_data, dpaa2_q->fqid); -#ifdef RTE_LIBRTE_IEEE1588 - /* IEEE1588 driver need pointer to tx confirmation queue - * corresponding to last packet transmitted for reading - * the timestamp - */ - if ((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - priv->next_tx_conf_queue = dpaa2_q->tx_conf_queue; - dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue); - priv->tx_timestamp = 0; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + return 0; } -#endif + hw_mp = priv->bp_list->mp; + + if (dpaa2_q->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q, false); /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc); @@ -1473,214 +1655,119 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) qbman_eq_desc_set_fq(&eqdesc, dpaa2_q->fqid); /*Clear the unused FD fields before sending*/ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn(*bufs)) { - uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; - - flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | - dqrr_index; - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); - *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; - } +tx_again: + /*Check if the queue is congested*/ + retry_count = 0; + while (qbman_result_SCN_state(dpaa2_q->cscn)) { + retry_count++; + /* Retry for some time before giving up */ + if (retry_count > CONG_RETRY_COUNT) + goto skip_tx; + } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], mempool_to_bpid(mp)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies - (rte_mempool_from_obj((void *)*bufs), - (void **)bufs, 1, 0); -#endif - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? + dpaa2_eqcr_size : nb_pkts; - if (unlikely(RTE_MBUF_HAS_EXTBUF(*bufs))) { - if (unlikely((*bufs)->nb_segs > 1)) { - mp = (*bufs)->pool; - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - mempool_to_bpid(mp))) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, 0); - } - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } + for (loop = 0; loop < frames_to_send; loop++) { + dy_conf[loop] = false; + if (*dpaa2_seqn(*bufs)) { + uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; + + flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; + DPAA2_PER_LCORE_DQRR_SIZE--; + DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); + *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; + } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); + if (unlikely((*bufs)->ol_flags + & RTE_MBUF_F_TX_VLAN)) { + ret = rte_vlan_insert(bufs); + if (ret) goto send_n_return; - } + } - if (unlikely((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN)) { - int ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR("S/G support not added" - " for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif + tstamp[loop] = false; + + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { bufs++; + continue; } - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], &flags[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); + } else { + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } + if (ret) + goto send_n_return; + bufs++; + } - num_tx += loop; - nb_pkts -= loop; + loop = 0; + retry_count = 0; + while (loop < frames_to_send) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, + &fd_arr[loop], &flags[loop], + frames_to_send - loop); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { + num_tx += loop; + nb_pkts -= loop; + goto send_n_return; + } + } else { + loop += ret; + retry_count = 0; + } } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); + num_tx += loop; + nb_pkts -= loop; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + for (i = 0; i < loop; i++) { + if (tstamp[i]) + dpaa2_q->tx_conf_queue->ts_to_cnfd++; + } } + if (nb_pkts > 0) + goto tx_again; + + dpaa2_q->tx_pkts += num_tx; return num_tx; send_n_return: /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[i], - &flags[i], - loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } + retry_count = 0; + i = 0; + while (i < loop) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, &fd_arr[i], + &flags[i], loop - i); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + break; + } else { + i += ret; + retry_count = 0; } - num_tx += i; } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); + num_tx += i; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + loop = i; + for (i = 0; i < loop; i++) { + if (tstamp[i]) + dpaa2_q->tx_conf_queue->ts_to_cnfd++; + } } - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; +skip_tx: dpaa2_q->tx_pkts += num_tx; return num_tx; @@ -1755,149 +1842,110 @@ dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_tx_multi_txq_ordered) uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, - struct rte_mbuf **bufs, uint16_t nb_pkts) + struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to multiple queues respectively.*/ - uint32_t loop, i, retry_count; - int32_t ret; + uint32_t loop, retry_count, sent = 0, i; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS]; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; - struct rte_mempool *mp; + struct rte_mempool *hw_mp; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; struct dpaa2_queue *dpaa2_q[MAX_TX_RING_SLOTS]; struct qbman_swp *swp; - uint16_t bpid; - struct rte_mbuf *mi; struct rte_eth_dev_data *eth_data; struct dpaa2_dev_priv *priv; struct dpaa2_queue *order_sendq; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } } swp = DPAA2_PER_LCORE_PORTAL; +tx_again: frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - dpaa2_q[loop] = (struct dpaa2_queue *)queue[loop]; + dpaa2_q[loop] = queue[loop]; + if (dpaa2_q[loop]->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q[loop], false); eth_data = dpaa2_q[loop]->eth_data; priv = eth_data->dev_private; - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { + dy_conf[loop] = false; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + ret = -ENOMEM; + goto send_frames; + } + hw_mp = priv->bp_list->mp; + if (!priv->en_loose_ordered && + (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP)) { + if (!num_free_eq_desc) { + num_free_eq_desc = dpaa2_free_eq_descriptors(); if (!num_free_eq_desc) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (!num_free_eq_desc) - goto send_frames; + ret = -EIO; + goto send_frames; } - num_free_eq_desc--; } + num_free_eq_desc--; } DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q[loop]->fqid); + eth_data, dpaa2_q[loop]->fqid); /* Check if the queue is congested */ retry_count = 0; while (qbman_result_SCN_state(dpaa2_q[loop]->cscn)) { retry_count++; /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) + if (retry_count > CONG_RETRY_COUNT) { + ret = -ETIME; goto send_frames; + } } /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); if (*dpaa2_seqn(*bufs) && priv->en_ordered) { - order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); + order_sendq = priv->tx_vq[0]; + dpaa2_set_enqueue_descriptor(order_sendq, *bufs, + &eqdesc[loop]); } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q[loop]->fqid); + qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); + qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_frames; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_frames; - } + tstamp[loop] = false; - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; + bufs++; + continue; + } - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_frames; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_frames; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_frames; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } - + if (ret) + goto send_frames; + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; bufs++; } @@ -1918,237 +1966,30 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, break; } } - - for (i = 0; i < free_count; i++) { - if (buf_to_free[i].pkt_id < loop) - rte_pktmbuf_free_seg(buf_to_free[i].seg); + nb_pkts -= loop; + sent += loop; + for (i = 0; i < loop; i++) { + if (tstamp[i] && dpaa2_q[i]->tx_conf_queue) + dpaa2_q[i]->tx_conf_queue->ts_to_cnfd++; } - return loop; + if (nb_pkts > 0 && !ret) + goto tx_again; + + return sent; } /* Callback to handle sending ordered packets through WRIOP based interface */ uint16_t -dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) +dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) { - /* Function to transmit the frames to given device and VQ*/ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_queue *order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; - struct rte_mempool *mp; - struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; - struct qbman_swp *swp; - uint32_t frames_to_send, num_free_eq_desc; - uint32_t loop, retry_count; - int32_t ret; - uint16_t num_tx = 0; - uint16_t bpid; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; - - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); - if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); - return 0; - } - } - swp = DPAA2_PER_LCORE_PORTAL; - - DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); + uint16_t i; + void *mq[nb_pkts]; - /* This would also handle normal and atomic queues as any type - * of packet can be enqueued when ordered queues are being used. - */ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (num_free_eq_desc < frames_to_send) - frames_to_send = num_free_eq_desc; - } - } - - for (loop = 0; loop < frames_to_send; loop++) { - /*Prepare enqueue descriptor*/ - qbman_eq_desc_clear(&eqdesc[loop]); - - if (*dpaa2_seqn(*bufs)) { - /* Use only queue 0 for Tx in case of atomic/ - * ordered packets as packets can get unordered - * when being transmitted out from the interface - */ - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); - } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q->fqid); - } - - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_n_return; - } - - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } - bufs++; - } + for (i = 0; i < nb_pkts; i++) + mq[i] = queue; - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[loop], &fd_arr[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } - } - - num_tx += loop; - nb_pkts -= loop; - } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; - -send_n_return: - /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[i], &fd_arr[i], loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } - } - num_tx += i; - } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; - dpaa2_q->tx_pkts += num_tx; - - return num_tx; + return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); } /* This function loopbacks all the received packets.*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 32/47] net/dpaa2: ptp enhancements 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (30 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 31/47] drivers: rework dpaa2 Tx confirmation Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 33/47] net/dpaa2: remove unused soft parser Tx code Prashant Gupta ` (15 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> 1) Correct TX timestamp only for PTP sync packets. 2) Runtime configure TX timestamp offset by parsing current TX PTP packet format. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 92 ++---------------- drivers/net/dpaa2/dpaa2_ethdev.h | 26 +++++ drivers/net/dpaa2/dpaa2_ptp.c | 161 +++++++++++++++++++++++++------ drivers/net/dpaa2/dpaa2_rxtx.c | 78 ++++++++++++++- 4 files changed, 239 insertions(+), 118 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 61b7ae138c..58b4cedee3 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -72,11 +72,6 @@ static uint64_t dev_tx_offloads_sup = static uint64_t dev_tx_offloads_nodis = RTE_ETH_TX_OFFLOAD_MULTI_SEGS; -/* enable timestamp in mbuf */ -bool dpaa2_enable_ts[RTE_MAX_ETHPORTS]; -uint64_t dpaa2_timestamp_rx_dynflag; -int dpaa2_timestamp_dynfield_offset = -1; - bool dpaa2_print_parser_result; /* Rx descriptor limit when DPNI loads PFDRs in PEB */ @@ -730,9 +725,6 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) int tx_l4_csum_offload = false; int ret, tc_index; uint32_t max_rx_pktlen; -#if defined(RTE_LIBRTE_IEEE1588) - uint16_t ptp_correction_offset; -#endif PMD_INIT_FUNC_TRACE(); @@ -814,25 +806,15 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) return ret; } -#if !defined(RTE_LIBRTE_IEEE1588) - if (rx_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) -#endif - { - ret = rte_mbuf_dyn_rx_timestamp_register( - &dpaa2_timestamp_dynfield_offset, - &dpaa2_timestamp_rx_dynflag); - if (ret != 0) { + if (rx_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) { + ret = rte_mbuf_dyn_rx_timestamp_register(&priv->rx_ts_offset, + &priv->rx_ts_flag); + if (ret) { DPAA2_PMD_ERR("Error to register timestamp field/flag"); - return -rte_errno; + return ret; } - dpaa2_enable_ts[dev->data->port_id] = true; } -#if defined(RTE_LIBRTE_IEEE1588) - /* By default setting ptp correction offset for Ethernet SYNC packets */ - ptp_correction_offset = RTE_ETHER_HDR_LEN + 8; - rte_pmd_dpaa2_set_one_step_ts(dev->data->port_id, ptp_correction_offset, 0); -#endif if (tx_offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) tx_l3_csum_offload = true; @@ -3315,8 +3297,6 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, - .mtr_ops_get = dpaa2_mtr_ops_get, -#if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, .timesync_read_time = dpaa2_timesync_read_time, @@ -3324,7 +3304,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .timesync_adjust_time = dpaa2_timesync_adjust_time, .timesync_read_rx_timestamp = dpaa2_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = dpaa2_timesync_read_tx_timestamp, -#endif + .mtr_ops_get = dpaa2_mtr_ops_get, }; /* Populate the mac address from physically available (u-boot/firmware) and/or @@ -3589,11 +3569,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->options = attr.options; priv->max_mac_filters = attr.mac_filter_entries; priv->max_vlan_filters = attr.vlan_filter_entries; - priv->flags = 0; -#if defined(RTE_LIBRTE_IEEE1588) - DPAA2_PMD_INFO("DPDK IEEE1588 is enabled"); - priv->flags |= DPAA2_TX_CONF_ENABLE; -#endif priv->tx_conf_type = DPAA2_TX_NO_CONF; /* Used with ``fslmc:dpni.1,drv_tx_conf=1`` */ @@ -3803,61 +3778,6 @@ rte_pmd_dpaa2_ep_name(uint32_t eth_id) return priv->ep_name; } -#if defined(RTE_LIBRTE_IEEE1588) -RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_get_one_step_ts, 24.11) -int -rte_pmd_dpaa2_get_one_step_ts(uint16_t port_id, bool mc_query) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = priv->eth_dev->process_private; - struct dpni_single_step_cfg ptp_cfg; - int err; - - if (!mc_query) - return priv->ptp_correction_offset; - - err = dpni_get_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &ptp_cfg); - if (err) { - DPAA2_PMD_ERR("Failed to retrieve onestep configuration"); - return err; - } - - if (!ptp_cfg.ptp_onestep_reg_base) { - DPAA2_PMD_ERR("1588 onestep reg not available"); - return -1; - } - - priv->ptp_correction_offset = ptp_cfg.offset; - - return priv->ptp_correction_offset; -} - -RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_set_one_step_ts, 24.11) -int -rte_pmd_dpaa2_set_one_step_ts(uint16_t port_id, uint16_t offset, uint8_t ch_update) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - struct dpni_single_step_cfg cfg; - int err; - - cfg.en = 1; - cfg.ch_update = ch_update; - cfg.offset = offset; - cfg.peer_delay = 0; - - err = dpni_set_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (err) - return err; - - priv->ptp_correction_offset = offset; - - return 0; -} -#endif - static int dpaa2_tx_sg_pool_init(void) { char name[RTE_MEMZONE_NAMESIZE]; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c9b7a8ae17..33195f0584 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -8,6 +8,9 @@ #ifndef _DPAA2_ETHDEV_H #define _DPAA2_ETHDEV_H +#include <rte_time.h> +#include <rte_log.h> +#include <rte_string_fns.h> #include <rte_compat.h> #include <rte_event_eth_rx_adapter.h> #include <rte_pmd_dpaa2.h> @@ -101,6 +104,11 @@ #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) +#define DPAA2_IEEE1588_DEBUG_FLAG RTE_BIT32(13) + +#define DPAA2_IEEE1588_TX_TS_FLAG RTE_BIT32(14) +#define DPAA2_IEEE1588_RX_TS_FLAG RTE_BIT32(15) + /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -589,6 +597,21 @@ dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, } } +static inline void +dpaa2_timestamp_debug(struct dpaa2_dev_priv *priv, + const char *prefix, uint64_t timestamp) +{ + struct timespec ts; + + if (likely(!(priv->flags & DPAA2_IEEE1588_DEBUG_FLAG))) + return; + + ts = rte_ns_to_timespec(timestamp); + fprintf(rte_log_get_stream(), + "DPAA2 TS DBG: %s: ns(%" PRIu64 ")->%ld seconds/%ld nanoseconds\n", + prefix, timestamp, ts.tv_sec, ts.tv_nsec); +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); @@ -651,6 +674,9 @@ void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); uint16_t dpaa2_dev_tx_conf(void *txq, int drain); +void +dpaa2_dev_tx_ptp_one_step_runtime(struct rte_eth_dev *dev, + struct rte_mbuf *buf, int *tstamp, int *set); int dpaa2_timesync_enable(struct rte_eth_dev *dev); int dpaa2_timesync_disable(struct rte_eth_dev *dev); int dpaa2_timesync_read_time(struct rte_eth_dev *dev, diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index c845291c68..171d8025e7 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2019, 2023 NXP + * Copyright 2019, 2023-2026 NXP */ #include <sys/queue.h> @@ -22,6 +22,7 @@ #include <dpaa2_ethdev.h> #include <dpaa2_pmd_logs.h> +#include <dpaax_ptp.h> struct dpaa2_dprtc_dev { struct fsl_mc_io dprtc; /** handle to DPRTC portal object */ @@ -30,52 +31,144 @@ struct dpaa2_dprtc_dev { }; static struct dpaa2_dprtc_dev *dprtc_dev; -int dpaa2_timesync_enable(struct rte_eth_dev *dev __rte_unused) +static int +dpaa2_timesync_set_one_step(struct rte_eth_dev *dev, + uint16_t offset, int udp) { + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = dev->process_private; + struct dpni_single_step_cfg cfg; + int err; + + memset(&cfg, 0, sizeof(struct dpni_single_step_cfg)); + cfg.en = 1; + cfg.ch_update = udp; + cfg.offset = offset; + cfg.peer_delay = 0; + + err = dpni_set_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg); + if (err) + return err; + + priv->ptp_correction_offset = offset; + return 0; } -int dpaa2_timesync_disable(struct rte_eth_dev *dev __rte_unused) +void +dpaa2_dev_tx_ptp_one_step_runtime(struct rte_eth_dev *dev, + struct rte_mbuf *buf, int *tstamp, int *set) { + uint16_t ts_offset; + int is_udp = false, ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (tstamp) + *tstamp = false; + if (set) + *set = false; + + if (!dpaax_timesync_ptp_parse_header(buf, + &ts_offset, &is_udp)) { + DPAA2_PMD_WARN("Tx packet is not PTP frame."); + ret = -EINVAL; + } else { + if (ts_offset != priv->ptp_correction_offset) { + ret = dpaa2_timesync_set_one_step(dev, ts_offset, is_udp); + if (ret) { + DPAA2_PMD_WARN("Change one step failed(%d)", ret); + } else { + DPAA2_PMD_INFO("Change one step from offset %d to %d", + priv->ptp_correction_offset, ts_offset); + priv->ptp_correction_offset = ts_offset; + if (set) + *set = true; + } + } + } + + if (!ret && tstamp) + *tstamp = true; +} + +int dpaa2_timesync_enable(struct rte_eth_dev *dev) +{ + uint16_t default_offset; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret; + + default_offset = RTE_ETHER_HDR_LEN + + offsetof(struct rte_dpaax_ptp_header, correction); + + ret = dpaa2_timesync_set_one_step(dev, default_offset, false); + if (ret) { + DPAA2_PMD_ERR("%s one step timesyc set failed(%d)", + dev->data->name, ret); + } else { + priv->flags |= DPAA2_IEEE1588_TX_TS_FLAG; + } + priv->flags |= DPAA2_IEEE1588_RX_TS_FLAG; + if (priv->tx_conf_type == DPAA2_TX_NO_CONF) { + DPAA2_PMD_WARN("%s Unable to read TX timestamp", + dev->data->name); + } + if (getenv("DPAA2_IEEE1588_DEBUG_ENABLE")) + priv->flags |= DPAA2_IEEE1588_DEBUG_FLAG; + + return 0; +} + +int dpaa2_timesync_disable(struct rte_eth_dev *dev) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + priv->ptp_correction_offset = 0; + priv->flags &= ~DPAA2_IEEE1588_RX_TS_FLAG; + priv->flags &= ~DPAA2_IEEE1588_TX_TS_FLAG; return 0; } int dpaa2_timesync_read_time(struct rte_eth_dev *dev, - struct timespec *timestamp) + struct timespec *timestamp) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ret = dprtc_get_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &ns); + dprtc_dev->token, &ns); if (ret) { DPAA2_PMD_ERR("dprtc_get_time failed ret: %d", ret); return ret; } *timestamp = rte_ns_to_timespec(ns); + dpaa2_timestamp_debug(priv, __func__, ns); return 0; } int dpaa2_timesync_write_time(struct rte_eth_dev *dev, - const struct timespec *ts) + const struct timespec *ts) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ns = rte_timespec_to_ns(ts); - ret = dprtc_set_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, ns); + dprtc_dev->token, ns); if (ret) { DPAA2_PMD_ERR("dprtc_set_time failed ret: %d", ret); return ret; } + dpaa2_timestamp_debug(priv, __func__, ns); return 0; } @@ -84,11 +177,13 @@ int dpaa2_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ret = dprtc_get_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &ns); + dprtc_dev->token, &ns); if (ret) { DPAA2_PMD_ERR("dprtc_get_time failed ret: %d", ret); return ret; @@ -102,64 +197,73 @@ int dpaa2_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) DPAA2_PMD_ERR("dprtc_set_time failed ret: %d", ret); return ret; } + dpaa2_timestamp_debug(priv, "adjust delata", delta); + dpaa2_timestamp_debug(priv, "adjust absolute", ns); return 0; } int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, - struct timespec *timestamp) + struct timespec *timestamp) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - if (priv->next_txq_to_cnf) { - while (!priv->tx_timestamp) - dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); - } else { - return -1; - } + if (!(priv->flags & DPAA2_IEEE1588_TX_TS_FLAG) || + priv->tx_conf_type == DPAA2_TX_NO_CONF) + return -EINVAL; + + while (priv->next_txq_to_cnf && + priv->next_txq_to_cnf->ts_to_cnfd > 0) + dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); + *timestamp = rte_ns_to_timespec(priv->tx_timestamp); + dpaa2_timestamp_debug(priv, __func__, priv->tx_timestamp); return 0; } int dpaa2_timesync_read_rx_timestamp(struct rte_eth_dev *dev, - struct timespec *timestamp, - uint32_t flags __rte_unused) + struct timespec *timestamp, uint32_t flags __rte_unused) { struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (!(priv->flags & DPAA2_IEEE1588_RX_TS_FLAG)) + return -EINVAL; + *timestamp = rte_ns_to_timespec(priv->rx_timestamp); + dpaa2_timestamp_debug(priv, __func__, priv->rx_timestamp); + return 0; } -#if defined(RTE_LIBRTE_IEEE1588) static int dpaa2_create_dprtc_device(int vdev_fd __rte_unused, struct vfio_device_info *obj_info __rte_unused, struct rte_dpaa2_device *obj) { struct dprtc_attr attr; - int ret, dprtc_id = obj->object_id; + int ret = 0, dprtc_id = obj->object_id; PMD_INIT_FUNC_TRACE(); /* Allocate DPAA2 dprtc handle */ - dprtc_dev = rte_malloc(NULL, sizeof(struct dpaa2_dprtc_dev), 0); + dprtc_dev = rte_zmalloc(NULL, sizeof(struct dpaa2_dprtc_dev), 0); if (!dprtc_dev) { DPAA2_PMD_ERR("Memory allocation failed for DPRTC Device"); - return -1; + return -ENOMEM; } /* Open the dprtc object */ dprtc_dev->dprtc.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); ret = dprtc_open(&dprtc_dev->dprtc, CMD_PRI_LOW, dprtc_id, - &dprtc_dev->token); + &dprtc_dev->token); if (ret) { DPAA2_PMD_ERR("Unable to open dprtc object: err(%d)", ret); goto init_err; } ret = dprtc_get_attributes(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &attr); + dprtc_dev->token, &attr); if (ret) { DPAA2_PMD_ERR("Unable to get dprtc attr: err(%d)", ret); goto init_err; @@ -172,7 +276,7 @@ dpaa2_create_dprtc_device(int vdev_fd __rte_unused, init_err: rte_free(dprtc_dev); - return -1; + return ret; } static struct rte_dpaa2_object rte_dpaa2_dprtc_obj = { @@ -181,4 +285,3 @@ static struct rte_dpaa2_object rte_dpaa2_dprtc_obj = { }; RTE_PMD_REGISTER_DPAA2_OBJECT(dprtc, rte_dpaa2_dprtc_obj); -#endif diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 3212790957..5c46c0f6d2 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -22,6 +22,7 @@ #include <dpaa2_hw_pvt.h> #include <dpaa2_hw_dpio.h> #include <dpaa2_hw_mempool.h> +#include <dpaax_ptp.h> #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" @@ -108,6 +109,30 @@ dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, m->hash.rss); } } + +static inline void +dpaa2_dev_rx_read_timestamp(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m) +{ + struct dpaa2_annot_hdr *annotation; + rte_mbuf_timestamp_t *ts; + + if (!(priv->flags & DPAA2_IEEE1588_RX_TS_FLAG)) + return; + + annotation = (void *)((uint8_t *)m->buf_addr + DPAA2_FD_PTA_SIZE); + if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) { + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST; + } + ts = RTE_MBUF_DYNFIELD(m, priv->rx_ts_offset, void *); + *ts = annotation->word2; + m->ol_flags |= priv->rx_ts_flag; + rte_atomic_store_explicit(&priv->rx_timestamp, *ts, + rte_memory_order_relaxed); + dpaa2_timestamp_debug(priv, __func__, priv->rx_timestamp); +} + static void __rte_hot dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, struct rte_mbuf *m, const struct qbman_fd *fd, @@ -948,6 +973,8 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, mbuf, fd); + dpaa2_dev_rx_read_timestamp(priv, mbuf); + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -1123,6 +1150,8 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); + dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1373,6 +1402,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); + dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1416,6 +1446,8 @@ dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, return true; } +#define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + uint16_t dpaa2_dev_tx_conf(void *txq, int drain) { /* Function receive frames for a given device and VQ*/ @@ -1433,7 +1465,10 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) struct rte_mbuf *mbufs[dpaa2_dqrr_size]; struct rte_mempool *mp = NULL; - #define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct dpaa2_annot_hdr *annotation; + void *v_addr; conf_again: bulk_free = true; @@ -1531,6 +1566,17 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) if (bulk_free == true && !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) bulk_free = false; + if (unlikely(mbufs[idx]->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)) { + v_addr = mbufs[idx]->buf_addr; + annotation = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); + rte_atomic_store_explicit(&priv->tx_timestamp, + annotation->word2, + rte_memory_order_relaxed); + rte_atomic_store_explicit(&priv->next_txq_to_cnf, + dpaa2_txq, rte_memory_order_relaxed); + dpaa2_q->ts_to_cnfd--; + dpaa2_timestamp_debug(priv, __func__, priv->tx_timestamp); + } idx++; dq_storage++; if (idx >= dpaa2_dqrr_size) @@ -1613,7 +1659,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ uint32_t loop, retry_count, i; - int32_t ret, tstamp[MAX_TX_RING_SLOTS]; + int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send; struct qbman_eq_desc eqdesc; @@ -1659,6 +1705,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) tx_again: /*Check if the queue is congested*/ retry_count = 0; + ptp_set_count = 0; while (qbman_result_SCN_state(dpaa2_q->cscn)) { retry_count++; /* Retry for some time before giving up */ @@ -1688,6 +1735,17 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } tstamp[loop] = false; + if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && + (priv->flags & DPAA2_IEEE1588_TX_TS_FLAG))) { + ptp_set = false; + dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, + &tstamp[loop], &ptp_set); + if (ptp_set) + ptp_set_count++; + if (ptp_set_count > 1) + DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); + goto skip_fast_mbuf2fd; + } ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, *bufs, &fd_arr[loop], priv->tx_conf_type); @@ -1696,6 +1754,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) continue; } +skip_fast_mbuf2fd: if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); @@ -1846,7 +1905,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, { /* Function to transmit the frames to multiple queues respectively.*/ uint32_t loop, retry_count, sent = 0, i; - int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS]; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; struct rte_mempool *hw_mp; @@ -1869,6 +1928,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, swp = DPAA2_PER_LCORE_PORTAL; tx_again: + ptp_set_count = 0; frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; @@ -1925,6 +1985,17 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, } tstamp[loop] = false; + if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && + (priv->flags & DPAA2_IEEE1588_TX_TS_FLAG))) { + ptp_set = false; + dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, + &tstamp[loop], &ptp_set); + if (ptp_set) + ptp_set_count++; + if (ptp_set_count > 1) + DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); + goto skip_fast_mbuf2fd; + } ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, *bufs, &fd_arr[loop], priv->tx_conf_type); @@ -1935,6 +2006,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, continue; } +skip_fast_mbuf2fd: if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 33/47] net/dpaa2: remove unused soft parser Tx code 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (31 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 32/47] net/dpaa2: ptp enhancements Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 34/47] net/dpaa2: update MC dpni QoS and flow steering API Prashant Gupta ` (14 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Remove the soft parser related code from the Tx path. The soft parser can only be loaded before Linux boots, so this code was never reachable at runtime. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_rxtx.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 5c46c0f6d2..6d17a4d160 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -162,16 +162,6 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; } } - if (priv->sp_protocol) { - if (frc_parse->fafe2) { - frc_parse->fafe2 = 0; - ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; - } - if (frc_parse->sum_l.l4.fafe3) { - frc_parse->sum_l.l4.fafe3 = 0; - ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; - } - } switch (frc) { case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | @@ -740,7 +730,7 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, if (mbuf->pool->ops_index == hw_mp->ops_index && RTE_MBUF_DIRECT(mbuf) && - (mbuf->data_off > RTE_ALIGN(sg_size + offset, 8))) { + mbuf->data_off > RTE_ALIGN(sg_size + offset, 8)) { sg_mbuf = mbuf; mp = mbuf->pool; if (need_conf) { @@ -1563,7 +1553,7 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) mp = mbufs[idx]->pool; if (unlikely(rte_mbuf_refcnt_read(mbufs[idx]) > 1)) bulk_free = false; - if (bulk_free == true && + if (bulk_free && !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) bulk_free = false; if (unlikely(mbufs[idx]->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 34/47] net/dpaa2: update MC dpni QoS and flow steering API 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (32 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 33/47] net/dpaa2: remove unused soft parser Tx code Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 35/47] net/dpaa2: enhance xstat implementation Prashant Gupta ` (13 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Update the MC firmware command interface for the QoS and flow steering (FS) tables ahead of the flow engine rework: - Version the SET_QOS_TBL / ADD_FS_ENT commands and add dpni_set_qos_table_v2() and dpni_add_fs_entry_legacy() wrappers. - Support a per-entry default flow id in the QoS table configuration. - Replace the single redirect_obj_token in dpni_fs_action_cfg with a redir_tokens[] array plus num_tokens, and program it via the new ADD_FS_ENT command. - Add the dpni dump-table structures. The existing flow code is updated to populate the new redir_tokens[] field so behaviour is unchanged. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 3 +- drivers/net/dpaa2/mc/dpni.c | 127 ++++++++++++++++++++-------- drivers/net/dpaa2/mc/fsl_dpni.h | 100 ++++++++++++++++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 30 ++++--- 4 files changed, 206 insertions(+), 54 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 06ec1a2660..88a639ba89 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4445,7 +4445,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, dest_q = dest_priv->tx_vq[0]; flow->fs_action_cfg.options = DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; - flow->fs_action_cfg.redirect_obj_token = + flow->fs_action_cfg.num_tokens = 1; + flow->fs_action_cfg.redir_tokens[0] = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index 17275b7195..8e4114e604 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #include <fsl_mc_sys.h> @@ -1937,32 +1937,43 @@ int dpni_get_queue_tx_confirmation_mode(struct fsl_mc_io *mc_io, * * Return: '0' on Success; Error code otherwise. */ -int dpni_set_qos_table(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_qos_tbl_cfg *cfg) +static int +_dpni_set_qos_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg, uint16_t cmd_id) { struct dpni_cmd_set_qos_table *cmd_params; struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL, - cmd_flags, - token); - cmd_params = (struct dpni_cmd_set_qos_table *)cmd.params; + cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, token); + cmd_params = (void *)cmd.params; cmd_params->default_tc = cfg->default_tc; cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova); - dpni_set_field(cmd_params->discard_on_miss, - ENABLE, - cfg->discard_on_miss); - dpni_set_field(cmd_params->discard_on_miss, - KEEP_QOS_ENTRIES, - cfg->keep_entries); + if (DPNI_CMD_VER(cmd_id) > DPNI_CMD_VERSION_2) + cmd_params->default_flow_id = cpu_to_le16(cfg->default_flow_id); + dpni_set_field(cmd_params->flags, DISCARD_ON_MISS, cfg->discard_on_miss); + dpni_set_field(cmd_params->flags, KEEP_QOS_ENTRIES, cfg->keep_entries); + if (DPNI_CMD_VER(cmd_id) > DPNI_CMD_VERSION_2) + dpni_set_field(cmd_params->flags, SET_DEFAULT_FLOW_ID, cfg->set_default_flow_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +int +dpni_set_qos_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg) +{ + return _dpni_set_qos_table(mc_io, cmd_flags, token, cfg, DPNI_CMDID_SET_QOS_TBL); +} + +int +dpni_set_qos_table_v2(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg) +{ + return _dpni_set_qos_table(mc_io, cmd_flags, token, cfg, DPNI_CMDID_SET_QOS_TBL_V2); +} + /** * dpni_add_qos_entry() - Add QoS mapping entry (to select a traffic class) * @mc_io: Pointer to MC portal's I/O object @@ -2086,6 +2097,7 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, { struct dpni_cmd_add_fs_entry *cmd_params; struct mc_command cmd = { 0 }; + int i; /* prepare command */ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT, @@ -2100,7 +2112,36 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, cmd_params->options = cpu_to_le16(action->options); cmd_params->flow_id = cpu_to_le16(action->flow_id); cmd_params->flc = cpu_to_le64(action->flc); - cmd_params->redir_token = cpu_to_le16(action->redirect_obj_token); + cmd_params->token_num = action->num_tokens; + for (i = 0; i < DPNI_FS_REDIR_MAX_NUM; i++) + cmd_params->redir_tokens[i] = cpu_to_le16(action->redir_tokens[i]); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_add_fs_entry_legacy(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, + uint8_t tc_id, uint16_t index, + const struct dpni_rule_cfg *cfg, + const struct dpni_fs_action_cfg *action) +{ + struct dpni_cmd_add_fs_entry *cmd_params; + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT_LEGACY, + cmd_flags, token); + cmd_params = (struct dpni_cmd_add_fs_entry *)cmd.params; + cmd_params->tc_id = tc_id; + cmd_params->key_size = cfg->key_size; + cmd_params->index = cpu_to_le16(index); + cmd_params->key_iova = cpu_to_le64(cfg->key_iova); + cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova); + cmd_params->options = cpu_to_le16(action->options); + cmd_params->flow_id = cpu_to_le16(action->flow_id); + cmd_params->flc = cpu_to_le64(action->flc); + cmd_params->redir_tokens[0] = cpu_to_le16(action->redir_tokens[0]); /* send command to mc*/ return mc_send_command(mc_io, &cmd); @@ -2169,30 +2210,16 @@ int dpni_clear_fs_entries(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } -/** - * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @tc_id: Traffic class selection (0-7) - * @cfg: Traffic class policing configuration - * - * Return: '0' on Success; error code otherwise. - */ -int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t tc_id, - const struct dpni_rx_tc_policing_cfg *cfg) +static int +_dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg, uint16_t cmd_id) { struct dpni_cmd_set_rx_tc_policing *cmd_params; struct mc_command cmd = { 0 }; - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_POLICING, - cmd_flags, - token); - cmd_params = (struct dpni_cmd_set_rx_tc_policing *)cmd.params; + cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, token); + cmd_params = (void *)cmd.params; dpni_set_field(cmd_params->mode_color, COLOR, cfg->default_color); dpni_set_field(cmd_params->mode_color, MODE, cfg->mode); dpni_set_field(cmd_params->units, UNITS, cfg->units); @@ -2207,6 +2234,34 @@ int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @tc_id: Traffic class selection (0-7) + * @cfg: Traffic class policing configuration + * + * Return: '0' on Success; error code otherwise. + */ +int +dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg) +{ + return _dpni_set_rx_tc_policing(mc_io, cmd_flags, token, tc_id, cfg, + DPNI_CMDID_SET_RX_TC_POLICING); +} + +int +dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg) +{ + return _dpni_set_rx_tc_policing(mc_io, cmd_flags, token, tc_id, cfg, + DPNI_CMDID_SET_RX_TC_POLICING_V1); +} + /** * dpni_get_rx_tc_policing() - Get Rx traffic class policing configuration * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index d227025e01..f315bb7004 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #ifndef __FSL_DPNI_H @@ -121,6 +121,9 @@ struct fsl_mc_io; * The stashing is enabled by default. */ #define DPNI_OPT_STASHING_DIS 0x002000 + +#define DPNI_OPT_V8_HAS_REPLICATION 0x00004000 + /* * PFDR in PEB mode (v1 layout). * The total number of Rx descriptors is limited to 11264 in this mode. @@ -1554,6 +1557,8 @@ struct dpni_qos_tbl_cfg { int discard_on_miss; int keep_entries; uint8_t default_tc; + int set_default_flow_id; + uint16_t default_flow_id; }; int dpni_set_qos_table(struct fsl_mc_io *mc_io, @@ -1561,6 +1566,11 @@ int dpni_set_qos_table(struct fsl_mc_io *mc_io, uint16_t token, const struct dpni_qos_tbl_cfg *cfg); +int dpni_set_qos_table_v2(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + const struct dpni_qos_tbl_cfg *cfg); + /** * struct dpni_rule_cfg - Rule configuration for table lookup * @key_iova: I/O virtual address of the key (must be in DMA-able memory) @@ -1573,6 +1583,10 @@ struct dpni_rule_cfg { uint8_t key_size; }; +#define DPNI_QOS_OPT_SET_TC_ONLY 0x0 +#define DPNI_QOS_OPT_SET_FLOW_ID 0x1 +#define DPNI_QOS_OPT_UPDATE_IF_EXISTS 0x2 + int dpni_add_qos_entry(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, @@ -1633,6 +1647,22 @@ int dpni_clear_qos_table(struct fsl_mc_io *mc_io, */ #define DPNI_FS_OPT_REDIRECT_TO_DPNI_TX 0x10 +/** + * Redirect matching traffic into multiple Tx queues of other dpni objects. + * The frame will be transmitted directly + */ +#define DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX 0x20 + +/** + * In case the FS rule already exists (key and mask), update its action. + * Cannot be used with the actions which redirect the frame towards other DPNIs. + */ +#define DPNI_FS_OPT_UPDATE_IF_EXISTS 0x40 + +#ifndef DPNI_FS_REDIR_MAX_NUM +#define DPNI_FS_REDIR_MAX_NUM 8 +#endif + /** * struct dpni_fs_action_cfg - Action configuration for table look-up * @flc: FLC value for traffic matching this rule. Please check the Frame @@ -1650,12 +1680,38 @@ int dpni_clear_qos_table(struct fsl_mc_io *mc_io, * - if DPNI_FS_OPT_DISCARD is cleared the frame will be enqueued in queue with * index provided in flow_id parameter. * @options: Any combination of DPNI_FS_OPT_ values. + * @token_num: Number of tokens supplied. For DPNI_FS_OPT_REDIRECT_TO_DPNI_RX + * or DPNI_FS_OPT_REDIRECT_TO_DPNI_TX, the token_num must be 1 since there is + * only one token which is necessary. Accepted values are in the + * [1-8] range in case a REDIRECT option is requested. + * @redir_tokens: Array of tokens that identify the object where frame is redirected + * when this rule is hit. This parameter is used only when one + * of the flags DPNI_FS_OPT_REDIRECT_TO_DPNI_RX, + * DPNI_FS_OPT_REDIRECT_TO_DPNI_TX or + * DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX is set. The tokens + * are obtained using dpni_open() API call. The objects must + * stay open during the operation to ensure the fact that + * application has access on them. + * If the object is destroyed of closed, the following actions + * will take place: + * - In case of DPNI_FS_OPT_REDIRECT_TO_DPNI_TX and + * DPNI_FS_OPT_REDIRECT_TO_DPNI_RX: + * + if DPNI_FS_OPT_DISCARD is set the frame will be + * discarded by current dpni + * + if DPNI_FS_OPT_DISCARD is cleared the frame will be + * enqueued in queue with index provided in flow_id + * parameter. + * - In case of DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX, the + * frame will be redirected to the remaining opened target + * DPNIs. If there are no more opened target DPNIs, the frame + * will be discarded. */ struct dpni_fs_action_cfg { uint64_t flc; uint16_t flow_id; - uint16_t redirect_obj_token; uint16_t options; + uint16_t num_tokens; + uint16_t redir_tokens[DPNI_FS_REDIR_MAX_NUM]; }; int dpni_add_fs_entry(struct fsl_mc_io *mc_io, @@ -1666,6 +1722,14 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, const struct dpni_rule_cfg *cfg, const struct dpni_fs_action_cfg *action); +int dpni_add_fs_entry_legacy(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + uint16_t index, + const struct dpni_rule_cfg *cfg, + const struct dpni_fs_action_cfg *action); + int dpni_remove_fs_entry(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, @@ -1928,7 +1992,7 @@ void dpni_extract_sw_sequence_layout(struct dpni_sw_sequence_layout *layout, * When used for queue_idx in function dpni_set_rx_dist_default_queue will signal to dpni * to drop all unclassified frames */ -#define DPNI_FS_MISS_DROP ((uint16_t)-1) +#define DPNI_FS_MISS_ACTION_DROP ((uint16_t)-1) /** * struct dpni_rx_dist_cfg - distribution configuration @@ -1941,9 +2005,10 @@ void dpni_extract_sw_sequence_layout(struct dpni_sw_sequence_layout *layout, * @enable: enable/disable the distribution. * @tc: TC id for which distribution is set * @fs_miss_flow_id: when packet misses all rules from flow steering table and hash is - * disabled it will be put into this queue id; use DPNI_FS_MISS_DROP to drop - * frames. The value of this field is used only when flow steering distribution - * is enabled and hash distribution is disabled + * disabled it will be put into this queue id; + * use DPNI_FS_MISS_ACTION_DROP to drop frames. + * The value of this field is used only when flow steering + * distribution is enabled and hash distribution is disabled. */ struct dpni_rx_dist_cfg { uint16_t dist_size; @@ -2035,6 +2100,29 @@ enum dpni_table_type { DPNI_VLAN_TABLE = 4, }; +struct __rte_packed_begin dpni_dump_table_header { + uint16_t table_type; + uint16_t table_num_entries; + uint16_t table_max_entries; + uint8_t default_action; + uint8_t match_type; + uint8_t reserved[24]; +} __rte_packed_end; + +struct __rte_packed_begin dpni_dump_table_entry { + uint8_t key[DPNI_MAX_KEY_SIZE]; + uint8_t mask[DPNI_MAX_KEY_SIZE]; + uint8_t key_action; + uint16_t result[3]; + uint16_t rule_index; + uint8_t reserved[19]; +} __rte_packed_end; + +struct __rte_packed_begin dpni_dump_table_rsp { + struct dpni_dump_table_header hdr; + struct dpni_dump_table_entry entry[]; +} __rte_packed_end; + int dpni_dump_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index 6b396ca7cc..36e4aacc3a 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #ifndef _FSL_DPNI_CMD_H @@ -20,6 +20,7 @@ #define DPNI_CMD_VERSION_7 7 #define DPNI_CMD_ID_OFFSET 4 +#define DPNI_CMD_VER(cmd_id) ((cmd_id) & ((1 << DPNI_CMD_ID_OFFSET) - 1)) #define DPNI_CMD(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_BASE_VERSION) #define DPNI_CMD_V2(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_VERSION_2) #define DPNI_CMD_V3(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_VERSION_3) @@ -77,13 +78,16 @@ #define DPNI_CMDID_SET_RX_TC_DIST DPNI_CMD_V4(0x235) -#define DPNI_CMDID_SET_RX_TC_POLICING DPNI_CMD(0x23E) +#define DPNI_CMDID_SET_RX_TC_POLICING_V1 DPNI_CMD(0x23E) +#define DPNI_CMDID_SET_RX_TC_POLICING DPNI_CMD_V2(0x23E) -#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD_V2(0x240) +#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD_V3(0x240) +#define DPNI_CMDID_SET_QOS_TBL_V2 DPNI_CMD_V2(0x240) #define DPNI_CMDID_ADD_QOS_ENT DPNI_CMD_V2(0x241) #define DPNI_CMDID_REMOVE_QOS_ENT DPNI_CMD(0x242) #define DPNI_CMDID_CLR_QOS_TBL DPNI_CMD(0x243) -#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD_V2(0x244) +#define DPNI_CMDID_ADD_FS_ENT_LEGACY DPNI_CMD_V2(0x244) +#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD_V3(0x244) #define DPNI_CMDID_REMOVE_FS_ENT DPNI_CMD(0x245) #define DPNI_CMDID_CLR_FS_ENT DPNI_CMD(0x246) @@ -584,19 +588,18 @@ struct dpni_cmd_set_queue { #define DPNI_DISCARD_ON_MISS_SIZE 1 #define DPNI_KEEP_QOS_ENTRIES_SHIFT 1 #define DPNI_KEEP_QOS_ENTRIES_SIZE 1 +#define DPNI_SET_DEFAULT_FLOW_ID_SHIFT 2 +#define DPNI_SET_DEFAULT_FLOW_ID_SIZE 1 struct dpni_cmd_set_qos_table { - uint32_t pad; + uint16_t pad; + uint16_t default_flow_id; uint8_t default_tc; - /* only the LSB */ - uint8_t discard_on_miss; + uint8_t flags; uint16_t pad1[21]; uint64_t key_cfg_iova; }; -#define DPNI_QOS_OPT_SET_TC_ONLY 0x0 -#define DPNI_QOS_OPT_SET_FLOW_ID 0x1 - struct dpni_cmd_add_qos_entry { uint8_t flags; uint8_t flow_id; @@ -616,6 +619,10 @@ struct dpni_cmd_remove_qos_entry { uint64_t mask_iova; }; +#ifndef DPNI_FS_REDIR_MAX_NUM +#define DPNI_FS_REDIR_MAX_NUM 8 +#endif + struct dpni_cmd_add_fs_entry { uint16_t options; uint8_t tc_id; @@ -625,7 +632,8 @@ struct dpni_cmd_add_fs_entry { uint64_t key_iova; uint64_t mask_iova; uint64_t flc; - uint16_t redir_token; + uint16_t redir_tokens[DPNI_FS_REDIR_MAX_NUM]; + uint8_t token_num; }; struct dpni_cmd_remove_fs_entry { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 35/47] net/dpaa2: enhance xstat implementation 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (33 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 34/47] net/dpaa2: update MC dpni QoS and flow steering API Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 36/47] net/dpaa2: rework flow engine Prashant Gupta ` (12 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> 1) Adapt RTE xstat API to return proper length. 2) Alloc DMA buffer of mac xstat only once. 3) Get MAC counter via dpni only when this dpni is connected to DPMAC. 4) Get TC policer counter only when meter flow of TC is there. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 913 +++++++++++++++++-------------- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +- drivers/net/dpaa2/mc/fsl_dpni.h | 259 +++++++-- 3 files changed, 738 insertions(+), 446 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 58b4cedee3..5e2011b911 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -26,6 +26,7 @@ #include <dpaa2_hw_pvt.h> #include <dpaa2_hw_mempool.h> #include <dpaa2_hw_dpio.h> +#include <fsl_dprc.h> #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" @@ -108,116 +109,268 @@ dpaa2_dist_size_is_supported(uint16_t n) int dpaa2_valid_dev; struct rte_mempool *dpaa2_tx_sg_pool; -struct rte_dpaa2_xstats_name_off { - char name[RTE_ETH_XSTATS_NAME_SIZE]; - uint8_t page_id; /* dpni statistics page id */ - uint8_t stats_id; /* stats id in the given page */ +struct dpaa2_xstats_seq { + struct dpni_statistics_page_0 pg0; + struct dpni_statistics_page_1 pg1; + struct dpni_statistics_page_2 pg2; + struct dpni_statistics_page_3 pg3; + struct dpni_statistics_page_4 pg4; + struct dpni_statistics_page_5 pg5[MAX_TCS]; + struct dpni_statistics_page_6 pg6; + struct dpni_dpmac_counters mac_cnt; }; -static const struct rte_dpaa2_xstats_name_off dpaa2_xstats_strings[] = { - {"ingress_multicast_frames", 0, 2}, - {"ingress_multicast_bytes", 0, 3}, - {"ingress_broadcast_frames", 0, 4}, - {"ingress_broadcast_bytes", 0, 5}, - {"egress_multicast_frames", 1, 2}, - {"egress_multicast_bytes", 1, 3}, - {"egress_broadcast_frames", 1, 4}, - {"egress_broadcast_bytes", 1, 5}, - {"ingress_filtered_frames", 2, 0}, - {"ingress_discarded_frames", 2, 1}, - {"ingress_nobuffer_discards", 2, 2}, - {"egress_discarded_frames", 2, 3}, - {"egress_confirmed_frames", 2, 4}, - {"cgr_reject_frames", 4, 0}, - {"cgr_reject_bytes", 4, 1}, - {"TC_0_policer_cnt_red", 5, 0}, - {"TC_0_policer_cnt_yellow", 5, 1}, - {"TC_0_policer_cnt_green", 5, 2}, - {"TC_0_policer_cnt_re_red", 5, 3}, - {"TC_0_policer_cnt_re_yellow", 5, 4}, - {"TC_1_policer_cnt_red", 6, 0}, - {"TC_1_policer_cnt_yellow", 6, 1}, - {"TC_1_policer_cnt_green", 6, 2}, - {"TC_1_policer_cnt_re_red", 6, 3}, - {"TC_1_policer_cnt_re_yellow", 6, 4}, - {"TC_2_policer_cnt_red", 7, 0}, - {"TC_2_policer_cnt_yellow", 7, 1}, - {"TC_2_policer_cnt_green", 7, 2}, - {"TC_2_policer_cnt_re_red", 7, 3}, - {"TC_2_policer_cnt_re_yellow", 7, 4}, - {"TC_3_policer_cnt_red", 8, 0}, - {"TC_3_policer_cnt_yellow", 8, 1}, - {"TC_3_policer_cnt_green", 8, 2}, - {"TC_3_policer_cnt_re_red", 8, 3}, - {"TC_3_policer_cnt_re_yellow", 8, 4}, - {"TC_4_policer_cnt_red", 9, 0}, - {"TC_4_policer_cnt_yellow", 9, 1}, - {"TC_4_policer_cnt_green", 9, 2}, - {"TC_4_policer_cnt_re_red", 9, 3}, - {"TC_4_policer_cnt_re_yellow", 9, 4}, - {"TC_5_policer_cnt_red", 10, 0}, - {"TC_5_policer_cnt_yellow", 10, 1}, - {"TC_5_policer_cnt_green", 10, 2}, - {"TC_5_policer_cnt_re_red", 10, 3}, - {"TC_5_policer_cnt_re_yellow", 10, 4}, - {"TC_6_policer_cnt_red", 11, 0}, - {"TC_6_policer_cnt_yellow", 11, 1}, - {"TC_6_policer_cnt_green", 11, 2}, - {"TC_6_policer_cnt_re_red", 11, 3}, - {"TC_6_policer_cnt_re_yellow", 11, 4}, - {"TC_7_policer_cnt_red", 12, 0}, - {"TC_7_policer_cnt_yellow", 12, 1}, - {"TC_7_policer_cnt_green", 12, 2}, - {"TC_7_policer_cnt_re_red", 12, 3}, - {"TC_7_policer_cnt_re_yellow", 12, 4}, - {"mac_rx_64 bytes", 0, 0}, - {"mac_rx_65-127 bytes", 0, 0}, - {"mac_rx_128-255 bytes", 0, 0}, - {"mac_rx_256-511 bytes", 0, 0}, - {"mac_rx_512-1023 bytes", 0, 0}, - {"mac_rx_1024-1518 bytes", 0, 0}, - {"mac_rx_1519-max bytes", 0, 0}, - {"mac_rx_frags", 0, 0}, - {"mac_rx_jabber", 0, 0}, - {"mac_rx_frame discards", 0, 0}, - {"mac_rx_align errors", 0, 0}, - {"mac_tx_undersized", 0, 0}, - {"mac_rx_oversized", 0, 0}, - {"mac_rx_pause", 0, 0}, - {"mac_tx_b-pause", 0, 0}, - {"mac_rx_bytes", 0, 0}, - {"mac_rx_m-cast", 0, 0}, - {"mac_rx_b-cast", 0, 0}, - {"mac_rx_all frames", 0, 0}, - {"mac_rx_u-cast", 0, 0}, - {"mac_rx_frame errors", 0, 0}, - {"mac_tx_bytes", 0, 0}, - {"mac_tx_m-cast", 0, 0}, - {"mac_tx_b-cast", 0, 0}, - {"mac_tx_u-cast", 0, 0}, - {"mac_tx_frame errors", 0, 0}, - {"mac_rx_frames ok", 0, 0}, - {"mac_tx_frames ok", 0, 0}, - {"mac_tx_64 bytes", 0, 0}, - {"mac_tx_65-127 bytes", 0, 0}, - {"mac_tx_128-255 bytes", 0, 0}, - {"mac_tx_256-511 bytes", 0, 0}, - {"mac_tx_512-1023 bytes", 0, 0}, - {"mac_tx_1024-1518 bytes", 0, 0}, - {"mac_tx_1519-max bytes", 0, 0}, - {"mac_rx_all_bytes", 0, 0}, - {"mac_rx_fcs_err", 0, 0}, - {"mac_rx_vlan_frame", 0, 0}, - {"mac_rx_undersized", 0, 0}, - {"mac_rx_control_frame", 0, 0}, - {"mac_rx_frame_discard_not_trunc", 0, 0}, - {"mac_tx_all_bytes", 0, 0}, - {"mac_tx_fcs_err", 0, 0}, - {"mac_tx_vlan_frame", 0, 0}, - {"mac_tx_all_frame", 0, 0}, - {"mac_tx_control_frame", 0, 0}, +#define DPAA2_XSTAT_MAX_NUM \ + (sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)) + +#define DPAA2_DPNI_XSTAT_MAX_NUM \ + (offsetof(struct dpaa2_xstats_seq, mac_cnt) / sizeof(uint64_t)) + +#define DPAA2_MAC_XSTAT_MAX_NUM DPAA2_MAC_NUM_STATS + +static_assert((DPAA2_DPNI_XSTAT_MAX_NUM + DPAA2_MAC_XSTAT_MAX_NUM) == + DPAA2_XSTAT_MAX_NUM, "DPNI and MAC xstats do not sum to total"); + +#define DPAA2_DPNI_STAT_SET_PAGE_PARAM(param) \ +({ \ + int ret = false; \ + \ + if ((id) >= this_offset && (id) < (this_offset + pg_size)) { \ + _stat_id = (id) - this_offset; \ + _param = param; \ + _size = pg_size; \ + ret = true; \ + } \ + ret; \ +}) + +#define DPAA2_DPNI_STAT_PAGE_PARAM(pid) \ +({ \ + uint64_t this_offset = offsetof(struct dpaa2_xstats_seq, pg##pid) / sizeof(uint64_t); \ + uint64_t pg_size = sizeof(struct dpni_statistics_page_##pid) / sizeof(uint64_t); \ + int ret; \ + \ + ret = DPAA2_DPNI_STAT_SET_PAGE_PARAM(0); \ + if (!ret) \ + _page++; \ + ret; \ +}) + +#define DPAA2_DPNI_STAT_POLICER_PAGE_PARAM() \ +({ \ + int ret = false; \ + uint8_t tc_id; \ + uint64_t this_offset; \ + uint64_t pg_size = sizeof(struct dpni_statistics_page_5) / sizeof(uint64_t); \ + \ + for (tc_id = 0; tc_id < MAX_TCS; tc_id++) { \ + this_offset = offsetof(struct dpaa2_xstats_seq, pg5[tc_id]) / sizeof(uint64_t); \ + ret = DPAA2_DPNI_STAT_SET_PAGE_PARAM(tc_id); \ + if (ret) \ + break; \ + } \ + if (!ret) \ + _page++; \ + ret; \ +}) + +static inline int +dpaa2_xstats_id_parse(uint32_t id, uint8_t *page, + uint8_t *stat_id, uint16_t *param, uint16_t *size) +{ + uint8_t _page = DPNI_INGRESS_STATISTICS_PAGE_ID, _stat_id = 0; + uint16_t _param = 0, _size = 0; + + if (DPAA2_DPNI_STAT_PAGE_PARAM(0)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(1)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(2)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(3)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(4)) + goto found_id; + if (DPAA2_DPNI_STAT_POLICER_PAGE_PARAM()) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(6)) + goto found_id; + + DPAA2_PMD_ERR("ID(%d) was not found in DPNI page statistics", id); + return -EINVAL; + +found_id: + if (page) + *page = _page; + if (stat_id) + *stat_id = _stat_id; + if (param) + *param = _param; + if (size) + *size = _size; + + return 0; +} + +#define DPAA2_XSTAT_ID(field) \ + (offsetof(struct dpaa2_xstats_seq, field) / sizeof(uint64_t)) + +#define DPAA2_XSTAT_STR_SET(pg, field) \ + [DPAA2_XSTAT_ID(pg.field)] = RTE_STR(field) + +#define DPAA2_XSTAT_TC_STR_SET(pg, tc, field) \ + [DPAA2_XSTAT_ID(pg[tc].field)] = "TC" RTE_STR(tc)"_" RTE_STR(field) + +#define DPAA2_XSTAT_TC_COLOR_STR_SET(pg, tc) \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_red), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_yellow), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_green), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_re_red), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_re_yellow) + +#define DPAA2_MAC_XSTAT_STR_SET(name) \ + [DPAA2_XSTAT_ID(mac_cnt.name)] = "mac_" RTE_STR(name) + +#define DPAA2_MAC_XSTAT_PFC_STR_SET(dir, tc) \ + [DPAA2_XSTAT_ID(mac_cnt.dir##_pfc_class[tc])] = \ + "mac_" RTE_STR(dir) "_pfc_class_" RTE_STR(tc) + +static const char * const +dpaa2_xstats_strings[DPAA2_XSTAT_MAX_NUM] = { + DPAA2_XSTAT_STR_SET(pg0, ingress_all_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_all_bytes), + DPAA2_XSTAT_STR_SET(pg0, ingress_multicast_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_multicast_bytes), + DPAA2_XSTAT_STR_SET(pg0, ingress_broadcast_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_broadcast_bytes), + + DPAA2_XSTAT_STR_SET(pg1, egress_all_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_all_bytes), + DPAA2_XSTAT_STR_SET(pg1, egress_multicast_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_multicast_bytes), + DPAA2_XSTAT_STR_SET(pg1, egress_broadcast_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_broadcast_bytes), + + DPAA2_XSTAT_STR_SET(pg2, ingress_filtered_frames), + DPAA2_XSTAT_STR_SET(pg2, ingress_discarded_frames), + DPAA2_XSTAT_STR_SET(pg2, ingress_nobuffer_discards), + DPAA2_XSTAT_STR_SET(pg2, egress_discarded_frames), + DPAA2_XSTAT_STR_SET(pg2, egress_confirmed_frames), + + DPAA2_XSTAT_STR_SET(pg3, ceetm_dequeue_bytes), + DPAA2_XSTAT_STR_SET(pg3, ceetm_dequeue_frames), + DPAA2_XSTAT_STR_SET(pg3, ceetm_reject_bytes), + DPAA2_XSTAT_STR_SET(pg3, ceetm_reject_frames), + + DPAA2_XSTAT_STR_SET(pg4, cgr_reject_frames), + DPAA2_XSTAT_STR_SET(pg4, cgr_reject_bytes), + + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 0), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 1), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 2), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 3), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 4), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 5), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 6), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 7), + + DPAA2_XSTAT_STR_SET(pg6, tx_pending_frames_cnt), + + DPAA2_MAC_XSTAT_STR_SET(rx_64_bytes), + DPAA2_MAC_XSTAT_STR_SET(rx_65_127_bytes), + DPAA2_MAC_XSTAT_STR_SET(rx_128_255_bytes), + DPAA2_MAC_XSTAT_STR_SET(rx_256_511_bytes), + DPAA2_MAC_XSTAT_STR_SET(rx_512_1023_bytes), + DPAA2_MAC_XSTAT_STR_SET(rx_1024_1518_bytes), + DPAA2_MAC_XSTAT_STR_SET(rx_1519_max_bytes), + + DPAA2_MAC_XSTAT_STR_SET(rx_fragments), + DPAA2_MAC_XSTAT_STR_SET(rx_jabber), + DPAA2_MAC_XSTAT_STR_SET(rx_drop_fifo), + DPAA2_MAC_XSTAT_STR_SET(rx_alignment_error), + + DPAA2_MAC_XSTAT_STR_SET(tx_undersize_good), + DPAA2_MAC_XSTAT_STR_SET(rx_oversize_good), + + DPAA2_MAC_XSTAT_STR_SET(rx_pause), + DPAA2_MAC_XSTAT_STR_SET(tx_pause), + + DPAA2_MAC_XSTAT_STR_SET(rx_good_bytes), + DPAA2_MAC_XSTAT_STR_SET(rx_multicast), + DPAA2_MAC_XSTAT_STR_SET(rx_broadcast), + DPAA2_MAC_XSTAT_STR_SET(rx_all_frames), + DPAA2_MAC_XSTAT_STR_SET(rx_unicast), + DPAA2_MAC_XSTAT_STR_SET(rx_error), + + DPAA2_MAC_XSTAT_STR_SET(tx_good_bytes), + DPAA2_MAC_XSTAT_STR_SET(tx_multicast), + DPAA2_MAC_XSTAT_STR_SET(tx_broadcast), + DPAA2_MAC_XSTAT_STR_SET(tx_unicast), + DPAA2_MAC_XSTAT_STR_SET(tx_error), + + DPAA2_MAC_XSTAT_STR_SET(rx_valid_frames), + DPAA2_MAC_XSTAT_STR_SET(tx_valid_frames), + + DPAA2_MAC_XSTAT_STR_SET(tx_64_bytes), + DPAA2_MAC_XSTAT_STR_SET(tx_65_127_bytes), + DPAA2_MAC_XSTAT_STR_SET(tx_128_255_bytes), + DPAA2_MAC_XSTAT_STR_SET(tx_256_511_bytes), + DPAA2_MAC_XSTAT_STR_SET(tx_512_1023_bytes), + DPAA2_MAC_XSTAT_STR_SET(tx_1024_1518_bytes), + DPAA2_MAC_XSTAT_STR_SET(tx_1519_max_bytes), + + DPAA2_MAC_XSTAT_STR_SET(rx_bytes_all), + DPAA2_MAC_XSTAT_STR_SET(rx_crc_error), + DPAA2_MAC_XSTAT_STR_SET(rx_vlan), + DPAA2_MAC_XSTAT_STR_SET(rx_undersize_good), + DPAA2_MAC_XSTAT_STR_SET(rx_ctrl_non_pause), + DPAA2_MAC_XSTAT_STR_SET(rx_drop_full), + + DPAA2_MAC_XSTAT_STR_SET(tx_bytes_all), + DPAA2_MAC_XSTAT_STR_SET(tx_crc_error), + DPAA2_MAC_XSTAT_STR_SET(tx_vlan), + DPAA2_MAC_XSTAT_STR_SET(tx_all_frames), + DPAA2_MAC_XSTAT_STR_SET(tx_ctrl_non_pause), + + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 0), + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 1), + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 2), + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 3), + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 4), + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 5), + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 6), + DPAA2_MAC_XSTAT_PFC_STR_SET(rx, 7), + + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 0), + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 1), + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 2), + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 3), + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 4), + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 5), + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 6), + DPAA2_MAC_XSTAT_PFC_STR_SET(tx, 7) }; +#define DPAA2_DPNI_XSTAT_FIELD_ID(field) \ + (offsetof(struct dpaa2_xstats_seq, field) / sizeof(uint64_t)) + +static const struct rte_eth_stats dpaa2_stats_xstat_ids = { + .ipackets = DPAA2_DPNI_XSTAT_FIELD_ID(pg0.ingress_all_frames), + .opackets = DPAA2_DPNI_XSTAT_FIELD_ID(pg1.egress_all_frames), + .ibytes = DPAA2_DPNI_XSTAT_FIELD_ID(pg0.ingress_all_bytes), + .obytes = DPAA2_DPNI_XSTAT_FIELD_ID(pg1.egress_all_bytes), + .imissed = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_filtered_frames), + .ierrors = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_discarded_frames), + .oerrors = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.egress_discarded_frames), + .rx_nombuf = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_nobuffer_discards) +}; + +#define DPAA2_STATS_XSTATS_NUM \ + (sizeof(dpaa2_stats_xstat_ids) / sizeof(uint64_t)) + +#define DPAA2_MAC_XSTATS_START_ID DPAA2_DPNI_XSTAT_MAX_NUM + + static struct rte_dpaa2_driver rte_dpaa2_pmd; static int dpaa2_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); @@ -1892,127 +2045,47 @@ dpaa2_dev_set_mac_addr(struct rte_eth_dev *dev, } static int -dpaa2_dev_stats_get(struct rte_eth_dev *dev, - struct rte_eth_stats *stats, struct eth_queue_stats *qstats) +dpaa2_dev_xstat_mac_setup_mem(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - int32_t retcode; - uint8_t page0 = 0, page1 = 1, page2 = 2; - union dpni_statistics value; - int i; - struct dpaa2_queue *dpaa2_rxq, *dpaa2_txq; - - memset(&value, 0, sizeof(union dpni_statistics)); - - PMD_INIT_FUNC_TRACE(); - - if (!dpni) { - DPAA2_PMD_ERR("dpni is NULL"); - return -EINVAL; - } - - if (!stats) { - DPAA2_PMD_ERR("stats is NULL"); - return -EINVAL; - } - - /*Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page0, 0, &value); - if (retcode) - goto err; - - stats->ipackets = value.page_0.ingress_all_frames; - stats->ibytes = value.page_0.ingress_all_bytes; - - /*Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page1, 0, &value); - if (retcode) - goto err; - - stats->opackets = value.page_1.egress_all_frames; - stats->obytes = value.page_1.egress_all_bytes; - - /*Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page2, 0, &value); - if (retcode) - goto err; - - /* Ingress drop frame count due to configured rules */ - stats->ierrors = value.page_2.ingress_filtered_frames; - /* Ingress drop frame count due to error */ - stats->ierrors += value.page_2.ingress_discarded_frames; - - stats->oerrors = value.page_2.egress_discarded_frames; - stats->imissed = value.page_2.ingress_nobuffer_discards; - - /* Fill in per queue stats */ - if (qstats != NULL) { - for (i = 0; (i < RTE_ETHDEV_QUEUE_STAT_CNTRS) && - (i < priv->nb_rx_queues || i < priv->nb_tx_queues); ++i) { - dpaa2_rxq = priv->rx_vq[i]; - dpaa2_txq = priv->tx_vq[i]; - if (dpaa2_rxq) - qstats->q_ipackets[i] = dpaa2_rxq->rx_pkts; - if (dpaa2_txq) - qstats->q_opackets[i] = dpaa2_txq->tx_pkts; + int ret = 0; - /* Byte counting is not implemented */ - qstats->q_ibytes[i] = 0; - qstats->q_obytes[i] = 0; + if (!priv->cnt_idx_dma_mem) { + priv->cnt_idx_dma_mem = rte_zmalloc(NULL, + DPAA2_MAC_STATS_INDEX_DMA_SIZE, RTE_CACHE_LINE_SIZE); + if (!priv->cnt_idx_dma_mem) { + ret = -ENOMEM; + DPAA2_PMD_ERR("Failure to allocate memory for mac index"); + goto out; } - } - return 0; - -err: - DPAA2_PMD_ERR("Operation not completed:Error Code = %d", retcode); - return retcode; -}; - -void -dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev) -{ - struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint32_t *cnt_idx; - int i; - - priv->cnt_idx_dma_mem = rte_malloc(NULL, DPAA2_MAC_STATS_INDEX_DMA_SIZE, - RTE_CACHE_LINE_SIZE); - if (!priv->cnt_idx_dma_mem) { - DPAA2_PMD_ERR("Failure to allocate memory for mac index"); - goto out; + priv->cnt_idx_iova = rte_mem_virt2iova(priv->cnt_idx_dma_mem); + if (priv->cnt_idx_iova == RTE_BAD_IOVA) { + ret = -ENOBUFS; + DPAA2_PMD_ERR("%s: No IOMMU map for count index dma mem(%p)", + __func__, priv->cnt_idx_dma_mem); + goto err_dma_map; + } } - priv->cnt_values_dma_mem = rte_malloc(NULL, DPAA2_MAC_STATS_VALUE_DMA_SIZE, - RTE_CACHE_LINE_SIZE); if (!priv->cnt_values_dma_mem) { - DPAA2_PMD_ERR("Failure to allocate memory for mac values"); - goto err_alloc_values; - } - - cnt_idx = priv->cnt_idx_dma_mem; - for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) - *cnt_idx++ = rte_cpu_to_le_32((uint32_t)i); - - priv->cnt_idx_iova = rte_mem_virt2iova(priv->cnt_idx_dma_mem); - if (priv->cnt_idx_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for count index dma mem(%p)", - __func__, priv->cnt_idx_dma_mem); - goto err_dma_map; - } - - priv->cnt_values_iova = rte_mem_virt2iova(priv->cnt_values_dma_mem); - if (priv->cnt_values_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for count values dma mem(%p)", - __func__, priv->cnt_values_dma_mem); - goto err_dma_map; + priv->cnt_values_dma_mem = rte_zmalloc(NULL, + DPAA2_MAC_STATS_VALUE_DMA_SIZE, RTE_CACHE_LINE_SIZE); + if (!priv->cnt_values_dma_mem) { + ret = -ENOMEM; + DPAA2_PMD_ERR("Failure to allocate memory for mac values"); + goto err_alloc_values; + } + priv->cnt_values_iova = rte_mem_virt2iova(priv->cnt_values_dma_mem); + if (priv->cnt_values_iova == RTE_BAD_IOVA) { + ret = -ENOBUFS; + DPAA2_PMD_ERR("%s: No IOMMU map for count values dma mem(%p)", + __func__, priv->cnt_values_dma_mem); + goto err_dma_map; + } } - return; + return 0; err_dma_map: rte_free(priv->cnt_values_dma_mem); @@ -2021,222 +2094,279 @@ dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev) out: priv->cnt_idx_dma_mem = NULL; priv->cnt_values_dma_mem = NULL; + + return ret; } -/* - * dpaa2_dev_xstats_get(): Get counters of dpni and dpmac. - * MAC (mac_*) counters are supported on MC version > 10.39.0 - * TC_x_policer_* counters are supported only when Policer is enable. - */ static int -dpaa2_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstat *xstats, unsigned int n) +dpaa2_dev_mac_xstats_avail(struct rte_eth_dev *dev) { - struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; - unsigned int i = 0, j = 0, num = RTE_DIM(dpaa2_xstats_strings); struct dpaa2_dev_priv *priv = dev->data->dev_private; - union dpni_statistics value[13] = {}; - struct dpni_rx_tc_policing_cfg cfg; - uint8_t page_id, stats_id; - uint64_t *cnt_values; - int32_t retcode; - int16_t tc; - - if (n < num) - return num; - - if (!xstats) - return 0; - - /* Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 0, 0, &value[0]); - if (retcode) - goto err; + uint64_t rev_mac_support; - /* Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 1, 0, &value[1]); - if (retcode) - goto err; - - /* Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 2, 0, &value[2]); - if (retcode) - goto err; - - for (j = 0; j < priv->max_cgs; j++) { - if (!priv->cgid_in_use[j]) { - /* Get Counters from page_4*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, - priv->token, - 4, 0, &value[4]); - if (retcode) - goto err; - break; - } - } + if (priv->ep_dev_type != DPAA2_MAC) + return false; - for (tc = 0; tc < priv->num_rx_tc; tc++) { - retcode = dpni_get_rx_tc_policing(dpni, CMD_PRI_LOW, - priv->token, tc, - &cfg); - if (retcode) { - DPAA2_PMD_ERR("Error to get the policer rule: %d", retcode); - goto err; - } + rev_mac_support = RTE_FSL_MC_REV(MC_VER_MAJOR, MC_VER_MINOR, 0); + if (priv->mc_rev >= rev_mac_support) + return true; - /* get policer stats if policer is enabled */ - if (cfg.mode != 0) { - /* Get Counters from page_5*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, - priv->token, 5, tc, - &value[(tc + 5)]); - if (retcode) - goto err; - } - } + return false; +} - while (i < (num - DPAA2_MAC_NUM_STATS)) { - xstats[i].id = i; - page_id = dpaa2_xstats_strings[i].page_id; - stats_id = dpaa2_xstats_strings[i].stats_id; - xstats[i].value = value[page_id].raw.counter[stats_id]; - i++; - } +static int +dpaa2_dev_dpni_xstats_avail(struct rte_eth_dev *dev, + uint8_t page_id, uint16_t param) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + uint8_t tc, i; - if (priv->cnt_idx_dma_mem && - !dpni_get_mac_statistics(dpni, CMD_PRI_LOW, priv->token, - priv->cnt_idx_iova, - priv->cnt_values_iova, - DPAA2_MAC_NUM_STATS)) { - cnt_values = priv->cnt_values_dma_mem; - while (i >= (num - DPAA2_MAC_NUM_STATS) && i < num) { - xstats[i].id = i; - xstats[i].value = rte_le_to_cpu_64(*cnt_values++); - i++; + if (page_id == DPNI_CGR_STATISTICS_PAGE_ID) { + for (i = 0; i < priv->max_cgs; i++) { + if (priv->cgid_in_use[i]) + return true; } - return i; - } - - while (i >= (num - DPAA2_MAC_NUM_STATS) && i < num) { - xstats[i].id = i; - xstats[i].value = 0; - i++; + } else if (page_id == DPNI_POLICER_STATISTICS_PAGE_ID) { + tc = param; + if (tc < MAX_TCS) + return true; + } else { + return true; } - return i; -err: - DPAA2_PMD_ERR("Error in obtaining extended stats (%d)", retcode); - return retcode; + return false; } static int -dpaa2_xstats_get_names(__rte_unused struct rte_eth_dev *dev, - struct rte_eth_xstat_name *xstats_names, - unsigned int limit) +dpaa2_dev_xstats_get_names(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, uint32_t limit) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); + uint16_t i, stat_cnt; + + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; + + if (!limit) + return stat_cnt; if (limit < stat_cnt) + stat_cnt = limit; + + if (!xstats_names) return stat_cnt; - if (xstats_names != NULL) - for (i = 0; i < stat_cnt; i++) - strlcpy(xstats_names[i].name, - dpaa2_xstats_strings[i].name, - sizeof(xstats_names[i].name)); + for (i = 0; i < stat_cnt; i++) + rte_strscpy(xstats_names[i].name, dpaa2_xstats_strings[i], + RTE_ETH_XSTATS_NAME_SIZE); return stat_cnt; } static int -dpaa2_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, - uint64_t *values, unsigned int n) +dpaa2_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, + uint64_t *values, uint32_t n) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); - uint64_t values_copy[stat_cnt]; - uint8_t page_id, stats_id; + uint16_t i, id, stat_cnt, mac_num = 0; + uint8_t page_id, stat_id; + uint16_t param; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = dev->process_private; + bool page_fetched[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; + /* Fetch required MAC counters in a single MC command. */ + int retcode; + uint32_t *mac_idx; + uint64_t *mac_val[DPAA2_MAC_XSTAT_MAX_NUM]; - if (!ids) { - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - int32_t retcode; - union dpni_statistics value[5] = {}; + retcode = dpaa2_dev_xstat_mac_setup_mem(dev); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to setup %s's MAC statistics!", + __func__, retcode, dev->data->name); + return retcode; + } + mac_idx = priv->cnt_idx_dma_mem; - if (n < stat_cnt) - return stat_cnt; + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; - if (!values) - return 0; + memset(page_fetched, 0, sizeof(page_fetched)); - /* Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 0, 0, &value[0]); + for (i = 0; i < n; i++) { + if (ids && ids[i] >= stat_cnt) { + DPAA2_PMD_ERR("xstats id value isn't valid"); + return -EINVAL; + } + id = ids ? ids[i] : i; + if (id >= DPAA2_MAC_XSTATS_START_ID) { + values[i] = 0; + /* ids[] is supplied by the application and may repeat + * the same MAC id, so bound the collection against the + * mac_idx[]/mac_val[] and DMA buffer capacity. + */ + if (dpaa2_dev_mac_xstats_avail(dev) && + mac_num < DPAA2_MAC_XSTAT_MAX_NUM) { + mac_idx[mac_num] = rte_cpu_to_le_32(id - DPAA2_MAC_XSTATS_START_ID); + mac_val[mac_num] = &values[i]; + mac_num++; + } + continue; + } + page_id = 0; + stat_id = 0; + param = 0; + retcode = dpaa2_xstats_id_parse(id, &page_id, &stat_id, ¶m, NULL); if (retcode) - return 0; + return retcode; + if (!dpaa2_dev_dpni_xstats_avail(dev, page_id, param)) { + values[i] = 0; + continue; + } + if (page_fetched[page_id][param]) { + values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; + continue; + } + /* Cache dpni page results: multiple xstats can share + * the same (page_id, param), so only fetch each pair once. + */ + retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, + priv->token, page_id, param, + &priv->pg_xstats[page_id][param]); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's statistcis of page%d!", + __func__, retcode, dev->data->name, page_id); + return retcode; + } + page_fetched[page_id][param] = true; + values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; + } - /* Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 1, 0, &value[1]); - if (retcode) - return 0; + if (mac_num > 0) { + retcode = dpni_get_mac_statistics(dpni, CMD_PRI_LOW, + priv->token, priv->cnt_idx_iova, + priv->cnt_values_iova, mac_num); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's %d MAC statistics!", + __func__, retcode, dev->data->name, mac_num); + return retcode; + } + for (i = 0; i < mac_num; i++) + *mac_val[i] = priv->cnt_values_dma_mem[i]; + } - /* Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 2, 0, &value[2]); - if (retcode) - return 0; + return n; +} - /* Get Counters from page_4*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 4, 0, &value[4]); - if (retcode) - return 0; +static int +dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, + const uint64_t *ids, struct rte_eth_xstat_name *xstats_names, + uint32_t limit) +{ + uint16_t i, stat_cnt; - for (i = 0; i < stat_cnt; i++) { - page_id = dpaa2_xstats_strings[i].page_id; - stats_id = dpaa2_xstats_strings[i].stats_id; - values[i] = value[page_id].raw.counter[stats_id]; - } - return stat_cnt; - } + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; - dpaa2_xstats_get_by_id(dev, NULL, values_copy, stat_cnt); + if (!ids) + return dpaa2_dev_xstats_get_names(dev, xstats_names, limit); - for (i = 0; i < n; i++) { + for (i = 0; i < limit; i++) { if (ids[i] >= stat_cnt) { - DPAA2_PMD_ERR("xstats id value isn't valid"); + DPAA2_PMD_ERR("xstats id[%d] value(%" PRIu64 ") >= max count(%d)", + i, ids[i], stat_cnt); return -EINVAL; } - values[i] = values_copy[ids[i]]; + rte_strscpy(xstats_names[i].name, + dpaa2_xstats_strings[ids[i]], + RTE_ETH_XSTATS_NAME_SIZE); } - return n; + return limit; } +/* + * dpaa2_dev_xstats_get(): Get counters of dpni and dpmac. + * MAC (mac_*) counters are supported on MC version > 10.39.0 + * TC_x_policer_* counters are supported only when Policer is enable. + */ static int -dpaa2_xstats_get_names_by_id(struct rte_eth_dev *dev, - const uint64_t *ids, - struct rte_eth_xstat_name *xstats_names, - unsigned int limit) +dpaa2_dev_xstats_get(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, uint32_t n) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); - struct rte_eth_xstat_name xstats_names_copy[stat_cnt]; + int retcode; + uint32_t i; + uint64_t ids[DPAA2_XSTAT_MAX_NUM], vals[DPAA2_XSTAT_MAX_NUM]; - if (!ids) - return dpaa2_xstats_get_names(dev, xstats_names, limit); + if (!xstats || !n) + return 0; + + if (n > DPAA2_XSTAT_MAX_NUM) { + DPAA2_PMD_WARN("%s: Expected xstat number(%d) > max(%ld)", + __func__, n, DPAA2_XSTAT_MAX_NUM); + n = DPAA2_XSTAT_MAX_NUM; + } + for (i = 0; i < n; i++) { + ids[i] = i; + xstats[i].id = i; + xstats[i].value = 0; + } - dpaa2_xstats_get_names(dev, xstats_names_copy, limit); + retcode = dpaa2_dev_xstats_get_by_id(dev, ids, vals, n); + if (retcode < 0) + return retcode; - for (i = 0; i < limit; i++) { - if (ids[i] >= stat_cnt) { - DPAA2_PMD_ERR("xstats id value isn't valid"); - return -1; + for (i = 0; i < (uint32_t)retcode; i++) + xstats[i].value = vals[i]; + + return retcode; +} + +static int +dpaa2_dev_stats_get(struct rte_eth_dev *dev, + struct rte_eth_stats *stats, struct eth_queue_stats *qstats) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int32_t retcode; + uint16_t i, num; + uint64_t ids[DPAA2_STATS_XSTATS_NUM], counts[DPAA2_STATS_XSTATS_NUM] = {0}; + struct dpaa2_queue *dpaa2_q; + + PMD_INIT_FUNC_TRACE(); + + rte_memcpy(ids, &dpaa2_stats_xstat_ids, sizeof(dpaa2_stats_xstat_ids)); + retcode = dpaa2_dev_xstats_get_by_id(dev, ids, counts, DPAA2_STATS_XSTATS_NUM); + if (retcode != RTE_DIM(ids)) { + DPAA2_PMD_ERR("%s: Failed to get xstats (%d)counters by %ld IDs", + __func__, retcode, DPAA2_STATS_XSTATS_NUM); + if (retcode >= 0) + retcode = -EINVAL; + return retcode; + } + + rte_memcpy(stats, counts, sizeof(struct rte_eth_stats)); + stats->imissed += stats->ierrors + stats->rx_nombuf; + + if (qstats) { + /* Fill in per queue stats */ + num = RTE_MIN(priv->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS); + for (i = 0; i < num; i++) { + dpaa2_q = priv->rx_vq[i]; + qstats->q_ipackets[i] = dpaa2_q->rx_pkts; + + /* Byte counting is not implemented */ + qstats->q_ibytes[i] = 0; + } + num = RTE_MIN(priv->nb_tx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS); + for (i = 0; i < num; i++) { + dpaa2_q = priv->tx_vq[i]; + qstats->q_opackets[i] = dpaa2_q->tx_pkts; + + /* Byte counting is not implemented */ + qstats->q_obytes[i] = 0; } - strcpy(xstats_names[i].name, xstats_names_copy[ids[i]].name); } - return limit; + + return 0; } static int @@ -2255,7 +2385,7 @@ dpaa2_dev_stats_reset(struct rte_eth_dev *dev) return -EINVAL; } - retcode = dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token); + retcode = dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token); if (retcode) goto error; @@ -3262,9 +3392,9 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .link_update = dpaa2_dev_link_update, .stats_get = dpaa2_dev_stats_get, .xstats_get = dpaa2_dev_xstats_get, - .xstats_get_by_id = dpaa2_xstats_get_by_id, - .xstats_get_names_by_id = dpaa2_xstats_get_names_by_id, - .xstats_get_names = dpaa2_xstats_get_names, + .xstats_get_by_id = dpaa2_dev_xstats_get_by_id, + .xstats_get_names_by_id = dpaa2_dev_xstats_get_names_by_id, + .xstats_get_names = dpaa2_dev_xstats_get_names, .stats_reset = dpaa2_dev_stats_reset, .xstats_reset = dpaa2_dev_stats_reset, .fw_version_get = dpaa2_fw_version_get, @@ -3719,17 +3849,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); - /* mac_statistics supported on MC version > 10.39.0 */ - { - struct mc_version mc_ver_info = {0}; - - if (!mc_get_version(dpni_dev, CMD_PRI_LOW, &mc_ver_info) && - mc_ver_info.major >= MC_VER_MAJOR && - mc_ver_info.minor >= MC_VER_MINOR && - mc_ver_info.revision > 0) - dpaa2_dev_mac_setup_stats(eth_dev); - } - return 0; init_err: dpaa2_dev_close(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 33195f0584..a76e7f9287 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -205,7 +205,8 @@ (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ -#define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) +#define DPAA2_MAC_NUM_STATS \ + (sizeof(struct dpni_dpmac_counters) / sizeof(uint64_t)) #define DPAA2_MAC_STATS_INDEX_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint32_t)) #define DPAA2_MAC_STATS_VALUE_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint64_t)) @@ -542,6 +543,12 @@ struct dpaa2_dev_priv { uint64_t cnt_idx_iova, cnt_values_iova; uint64_t mc_rev; + /* Cache one dpni_statistics result per (page_id, param) pair to avoid + * redundant MC commands when multiple xstats share the same page. + * Put it in heap to avoid allocating multi-KB stack in runtime. + */ + union dpni_statistics pg_xstats[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; + struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; LIST_HEAD(, dpaa2_dev_meter_profile) profiles; @@ -703,7 +710,4 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); -void -dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); - #endif /* _DPAA2_ETHDEV_H */ diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index f315bb7004..bc895234f1 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -688,50 +688,77 @@ int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, * @page_6.tx_pending_frames_cnt: total number of frames pending in Tx queues * @raw: raw statistics structure, used to index counters */ +enum dpni_statistics_page_id { + DPNI_INGRESS_STATISTICS_PAGE_ID = 0, + DPNI_EGRESS_STATISTICS_PAGE_ID = 1, + DPNI_ERR_STATISTICS_PAGE_ID = 2, + DPNI_CEETM_STATISTICS_PAGE_ID = 3, + DPNI_CGR_STATISTICS_PAGE_ID = 4, + DPNI_POLICER_STATISTICS_PAGE_ID = 5, + DPNI_TX_PENDING_STATISTICS_PAGE_ID = 6, + DPNI_MAX_STATISTICS_PAGE_ID +}; + +struct dpni_statistics_page_0 { + uint64_t ingress_all_frames; + uint64_t ingress_all_bytes; + uint64_t ingress_multicast_frames; + uint64_t ingress_multicast_bytes; + uint64_t ingress_broadcast_frames; + uint64_t ingress_broadcast_bytes; +}; + +struct dpni_statistics_page_1 { + uint64_t egress_all_frames; + uint64_t egress_all_bytes; + uint64_t egress_multicast_frames; + uint64_t egress_multicast_bytes; + uint64_t egress_broadcast_frames; + uint64_t egress_broadcast_bytes; +}; + +struct dpni_statistics_page_2 { + uint64_t ingress_filtered_frames; + uint64_t ingress_discarded_frames; + uint64_t ingress_nobuffer_discards; + uint64_t egress_discarded_frames; + uint64_t egress_confirmed_frames; +}; + +struct dpni_statistics_page_3 { + uint64_t ceetm_dequeue_bytes; + uint64_t ceetm_dequeue_frames; + uint64_t ceetm_reject_bytes; + uint64_t ceetm_reject_frames; +}; + +struct dpni_statistics_page_4 { + uint64_t cgr_reject_frames; + uint64_t cgr_reject_bytes; +}; + +struct dpni_statistics_page_5 { + uint64_t policer_cnt_red; + uint64_t policer_cnt_yellow; + uint64_t policer_cnt_green; + uint64_t policer_cnt_re_red; + uint64_t policer_cnt_re_yellow; +}; + +struct dpni_statistics_page_6 { + uint64_t tx_pending_frames_cnt; +}; + +#define DPNI_STAT_MAX_PARAM DPNI_MAX_TC + union dpni_statistics { - struct { - uint64_t ingress_all_frames; - uint64_t ingress_all_bytes; - uint64_t ingress_multicast_frames; - uint64_t ingress_multicast_bytes; - uint64_t ingress_broadcast_frames; - uint64_t ingress_broadcast_bytes; - } page_0; - struct { - uint64_t egress_all_frames; - uint64_t egress_all_bytes; - uint64_t egress_multicast_frames; - uint64_t egress_multicast_bytes; - uint64_t egress_broadcast_frames; - uint64_t egress_broadcast_bytes; - } page_1; - struct { - uint64_t ingress_filtered_frames; - uint64_t ingress_discarded_frames; - uint64_t ingress_nobuffer_discards; - uint64_t egress_discarded_frames; - uint64_t egress_confirmed_frames; - } page_2; - struct { - uint64_t ceetm_dequeue_bytes; - uint64_t ceetm_dequeue_frames; - uint64_t ceetm_reject_bytes; - uint64_t ceetm_reject_frames; - } page_3; - struct { - uint64_t cgr_reject_frames; - uint64_t cgr_reject_bytes; - } page_4; - struct { - uint64_t policer_cnt_red; - uint64_t policer_cnt_yellow; - uint64_t policer_cnt_green; - uint64_t policer_cnt_re_red; - uint64_t policer_cnt_re_yellow; - } page_5; - struct { - uint64_t tx_pending_frames_cnt; - } page_6; + struct dpni_statistics_page_0 page_0; + struct dpni_statistics_page_1 page_1; + struct dpni_statistics_page_2 page_2; + struct dpni_statistics_page_3 page_3; + struct dpni_statistics_page_4 page_4; + struct dpni_statistics_page_5 page_5; + struct dpni_statistics_page_6 page_6; struct { uint64_t counter[DPNI_STATISTICS_CNT]; } raw; @@ -2147,9 +2174,151 @@ int dpni_set_sp_profile(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t to int dpni_sp_enable(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t type, uint8_t en); -int dpni_get_mac_statistics(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, - uint64_t iova_cnt, uint64_t iova_values, uint32_t num_cnt); +struct dpni_dpmac_counters { + /** 0x00: Counts received 64-bytes frames, good or bad */ + uint64_t rx_64_bytes; + + /** 0x01: Counts received 65- to 127-bytes frames, good or bad */ + uint64_t rx_65_127_bytes; + + /** 0x02: Counts received 128- to 255-bytes frames, good or bad */ + uint64_t rx_128_255_bytes; + + /** 0x03: Counts received 256- to 511-bytes frames, good or bad */ + uint64_t rx_256_511_bytes; + + /** 0x04: Counts received 512- to 1023-bytes frames, good or bad */ + uint64_t rx_512_1023_bytes; + + /** 0x05: Counts received 1024- to 1518-bytes frames, good or bad */ + uint64_t rx_1024_1518_bytes; + + /** 0x06: Counts received frames >=1519 bytes */ + uint64_t rx_1519_max_bytes; + + /** 0x07: <64B frames with bad CRC */ + uint64_t rx_fragments; + + /** 0x08: >max length frames with bad FCS */ + uint64_t rx_jabber; + + /** 0x09: FIFO overflow drops (including truncated frames) */ + uint64_t rx_drop_fifo; + + /** 0x0A: Alignment error frames */ + uint64_t rx_alignment_error; + + /** 0x0B: TX <64B frames with good CRC */ + uint64_t tx_undersize_good; + /** 0x0C: >max length frames with good FCS */ + uint64_t rx_oversize_good; + + /** 0x0D: Received pause frames (including PFC) */ + uint64_t rx_pause; + + /** 0x0E: Transmitted pause frames (including PFC) */ + uint64_t tx_pause; + + /** 0x0F: Received bytes (valid frames, exclude preamble) */ + uint64_t rx_good_bytes; + + /** 0x10: Received multicast frames */ + uint64_t rx_multicast; + + /** 0x11: Received broadcast frames */ + uint64_t rx_broadcast; + + /** 0x12: Received frames (good + bad) */ + uint64_t rx_all_frames; + + /** 0x13: Received unicast frames */ + uint64_t rx_unicast; + + /** 0x14: Received error frames (excluding fragments) */ + uint64_t rx_error; + + /** 0x15: Transmitted bytes (valid frames) */ + uint64_t tx_good_bytes; + + /** 0x16: Transmitted multicast frames */ + uint64_t tx_multicast; + + /** 0x17: Transmitted broadcast frames */ + uint64_t tx_broadcast; + + /** 0x18: Transmitted unicast frames */ + uint64_t tx_unicast; + + /** 0x19: Transmitted error frames */ + uint64_t tx_error; + + /** 0x1A: Received valid frames (no error) */ + uint64_t rx_valid_frames; + + /** 0x1B: Transmitted valid frames (no error) */ + uint64_t tx_valid_frames; + + /** 0x1C: TX 64-byte frames */ + uint64_t tx_64_bytes; + + /** 0x1D: TX 65-127-byte frames */ + uint64_t tx_65_127_bytes; + + /** 0x1E: TX 128-255-byte frames */ + uint64_t tx_128_255_bytes; + + /** 0x1F: TX 256-511-byte frames */ + uint64_t tx_256_511_bytes; + + /** 0x20: TX 512-1023-byte frames */ + uint64_t tx_512_1023_bytes; + + /** 0x21: TX 1024-1518-byte frames */ + uint64_t tx_1024_1518_bytes; + + /** 0x22: TX >=1519-byte frames */ + uint64_t tx_1519_max_bytes; + + /** 0x23: RX bytes (good + bad frames) */ + uint64_t rx_bytes_all; + + /** 0x24: RX CRC-32 error frames */ + uint64_t rx_crc_error; + + /** 0x25: Valid VLAN-tagged RX frames */ + uint64_t rx_vlan; + + /** 0x26: RX <64B frames with good CRC */ + uint64_t rx_undersize_good; + + /** 0x27: RX control frames (0x8808, non-pause) */ + uint64_t rx_ctrl_non_pause; + + /** 0x28: Fully dropped frames due to MAC client FIFO overflow */ + uint64_t rx_drop_full; + + /** 0x29: TX bytes (good + bad frames) */ + uint64_t tx_bytes_all; + + /** 0x2A: TX CRC-32 error frames */ + uint64_t tx_crc_error; + + /** 0x2B: Valid VLAN-tagged TX frames */ + uint64_t tx_vlan; + + /** 0x2C: All TX frames (good + bad) */ + uint64_t tx_all_frames; + + /** 0x2D: TX control frames (0x8808, non-pause) */ + uint64_t tx_ctrl_non_pause; + + /** 0x2E-0x35: RX PFC frames per priority (0-7) */ + uint64_t rx_pfc_class[DPNI_MAX_TC]; + + /** 0x36-0x3D: TX PFC frames per priority (0-7) */ + uint64_t tx_pfc_class[DPNI_MAX_TC]; +}; int dpni_get_mac_statistics(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint64_t iova_cnt, uint64_t iova_values, uint32_t num_cnt); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 36/47] net/dpaa2: rework flow engine 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (34 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 35/47] net/dpaa2: enhance xstat implementation Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 37/47] net/dpaa2: support GENEVE flow item Prashant Gupta ` (11 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Rework the dpaa2 flow engine so that flow rules are programmed through the updated QoS and flow steering (FS) table interface. The distribution helpers in base/dpaa2_hw_dpni.c are removed and folded into the ethdev and flow code, which removes a layer of indirection and keeps the key extraction, RSS distribution and QoS/FS entry programming together in one place. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 546 -- drivers/net/dpaa2/dpaa2_ethdev.c | 399 +- drivers/net/dpaa2/dpaa2_ethdev.h | 482 +- drivers/net/dpaa2/dpaa2_flow.c | 6439 +++++++++++++----------- drivers/net/dpaa2/meson.build | 3 +- 5 files changed, 4119 insertions(+), 3750 deletions(-) delete mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni.c diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c deleted file mode 100644 index fee96b3529..0000000000 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c +++ /dev/null @@ -1,546 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2021,2023-2025 NXP - * - */ - -#include <time.h> -#include <net/if.h> - -#include <eal_export.h> -#include <rte_mbuf.h> -#include <ethdev_driver.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <rte_cycles.h> -#include <rte_kvargs.h> -#include <dev_driver.h> - -#include <dpaa2_pmd_logs.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_mempool.h> - -#include "../dpaa2_ethdev.h" - -int -dpaa2_distset_to_dpkg_profile_cfg( - uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg); - -RTE_EXPORT_SYMBOL(rte_pmd_dpaa2_set_custom_hash) -int -rte_pmd_dpaa2_set_custom_hash(uint16_t port_id, - uint16_t offset, uint8_t size) -{ - struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; - struct dpni_rx_tc_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret, tc_index = 0; - - if (!rte_eth_dev_is_valid_port(port_id)) { - DPAA2_PMD_WARN("Invalid port id %u", port_id); - return -EINVAL; - } - - if (strcmp(eth_dev->device->driver->name, - RTE_STR(NET_DPAA2_PMD_DRIVER_NAME))) { - DPAA2_PMD_WARN("Not a valid dpaa2 port"); - return -EINVAL; - } - - p_params = rte_zmalloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(&kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); - kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_DATA; - kg_cfg.extracts[0].extract.from_data.offset = offset; - kg_cfg.extracts[0].extract.from_data.size = size; - kg_cfg.extracts[0].num_of_byte_masks = 0; - kg_cfg.num_extracts = 1; - - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.dist_size = eth_dev->data->nb_rx_queues; - tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; - - ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, - &tc_cfg); - rte_free(p_params); - if (ret) { - DPAA2_PMD_ERR("Set RX TC dist failed(err=%d)", ret); - return ret; - } - - return 0; -} - -int -dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - int tc_dist_queues; - - /* TC distribution size is set with dist_queues or - * (nb_rx_queues - tc_index*dist_queues) in order of TC priority index. - */ - tc_dist_queues = eth_dev->data->nb_rx_queues - - tc_index * priv->dist_queues; - if (tc_dist_queues <= 0) { - DPAA2_PMD_INFO("No distribution on TC%d", tc_index); - return 0; - } - - if (tc_dist_queues > priv->dist_queues) - tc_dist_queues = priv->dist_queues; - - return dpaa2_setup_flow_dist_size(eth_dev, req_dist_set, - tc_index, tc_dist_queues); -} - -int -dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index, uint16_t dist_size) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = eth_dev->process_private; - struct dpni_rx_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret; - - if (dist_size == 0) - return 0; - - p_params = rte_malloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(p_params, 0, DIST_PARAM_IOVA_SIZE); - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - - ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg); - if (ret) { - DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported", - req_dist_set); - rte_free(p_params); - return ret; - } - - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.dist_size = dist_size; - tc_cfg.enable = true; - tc_cfg.tc = tc_index; - - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); - rte_free(p_params); - if (ret) { - DPAA2_PMD_ERR("RX Hash dist for failed(err=%d)", ret); - return ret; - } - - if (tc_index < MAX_TCS) - priv->dist_size_cur[tc_index] = dist_size; - - return 0; -} - -int -dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev, - uint8_t tc_index) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; - struct dpni_rx_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret; - - p_params = rte_malloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - tc_cfg.dist_size = 0; - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.enable = true; - tc_cfg.tc = tc_index; - - memset(p_params, 0, DIST_PARAM_IOVA_SIZE); - kg_cfg.num_extracts = 0; - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, - &tc_cfg); - rte_free(p_params); - if (ret) - DPAA2_PMD_ERR("RX hash dist failed(err=%d)", ret); - return ret; -} - -int -dpaa2_distset_to_dpkg_profile_cfg( - uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg) -{ - uint32_t loop = 0, i = 0; - uint64_t dist_field = 0; - int l2_configured = 0, l3_configured = 0; - int l4_configured = 0; - int mpls_configured = 0; - int vlan_configured = 0; - int esp_configured = 0; - int ah_configured = 0; - int pppoe_configured = 0; - - memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); - while (req_dist_set) { - if (req_dist_set % 2 != 0) { - dist_field = 1ULL << loop; - switch (dist_field) { - case RTE_ETH_RSS_L2_PAYLOAD: - case RTE_ETH_RSS_ETH: - if (l2_configured) - break; - l2_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_ETH; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_ETH_TYPE; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_PPPOE: - if (pppoe_configured) - break; - pppoe_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_PPPOE; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_PPPOE_SID; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_ESP: - if (esp_configured) - break; - esp_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IPSEC_ESP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IPSEC_ESP_SPI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_AH: - if (ah_configured) - break; - ah_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IPSEC_AH; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IPSEC_AH_SPI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_C_VLAN: - case RTE_ETH_RSS_S_VLAN: - if (vlan_configured) - break; - vlan_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_VLAN; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_VLAN_TCI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_MPLS: - - if (mpls_configured) - break; - mpls_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_1; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_2; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_N; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_IPV4: - case RTE_ETH_RSS_FRAG_IPV4: - case RTE_ETH_RSS_NONFRAG_IPV4_OTHER: - case RTE_ETH_RSS_IPV6: - case RTE_ETH_RSS_FRAG_IPV6: - case RTE_ETH_RSS_NONFRAG_IPV6_OTHER: - case RTE_ETH_RSS_IPV6_EX: - - if (l3_configured) - break; - l3_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IP_SRC; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IP_DST; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IP_PROTO; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_NONFRAG_IPV4_TCP: - case RTE_ETH_RSS_NONFRAG_IPV6_TCP: - case RTE_ETH_RSS_NONFRAG_IPV4_UDP: - case RTE_ETH_RSS_NONFRAG_IPV6_UDP: - case RTE_ETH_RSS_IPV6_TCP_EX: - case RTE_ETH_RSS_IPV6_UDP_EX: - case RTE_ETH_RSS_NONFRAG_IPV4_SCTP: - case RTE_ETH_RSS_NONFRAG_IPV6_SCTP: - - if (l4_configured) - break; - l4_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_TCP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_TCP_PORT_SRC; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_TCP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_TCP_PORT_DST; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - default: - DPAA2_PMD_WARN( - "unsupported flow dist option 0x%" PRIx64, - dist_field); - return -EINVAL; - } - } - req_dist_set = req_dist_set >> 1; - loop++; - } - kg_cfg->num_extracts = i; - return 0; -} - -int -dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, - struct fsl_mc_io *dpni, void *blist) -{ - /* Function to attach a DPNI with a buffer pool list. Buffer pool list - * handle is passed in blist. - */ - int32_t retcode; - struct dpni_pools_cfg bpool_cfg; - struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist; - struct dpni_buffer_layout layout; - int tot_size; - - /* ... rx buffer layout . - * Check alignment for buffer layouts first - */ - - /* ... rx buffer layout ... */ - if (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) { - int out_min_hdr_room, in_min_hdr_room; - /** Additional headroom layout for IPSec with TX configure - * dynamic enabled. - */ - in_min_hdr_room = DPAA2_RX_MIN_FD_OFFSET + - DPAA2_SEC_SIMPLE_FD_IB_MIN; - out_min_hdr_room = DPAA2_DYN_TX_MIN_FD_OFFSET + - DPAA2_SEC_SIMPLE_FD_OB_MIN; - tot_size = RTE_MAX(in_min_hdr_room, out_min_hdr_room); - if (tot_size < RTE_PKTMBUF_HEADROOM) - tot_size = RTE_PKTMBUF_HEADROOM; - } else { - tot_size = RTE_PKTMBUF_HEADROOM; - } - tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN); - - memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | - DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | - DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | - DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | - DPNI_BUF_LAYOUT_OPT_TIMESTAMP | - DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; - - layout.pass_timestamp = true; - layout.pass_frame_status = 1; - layout.private_data_size = DPAA2_FD_PTA_SIZE; - layout.pass_parser_result = 1; - layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN; - layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - - DPAA2_MBUF_HW_ANNOTATION; - retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX, &layout); - if (retcode) { - DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)", - retcode); - return retcode; - } - - /*Attach buffer pool to the network interface as described by the user*/ - memset(&bpool_cfg, 0, sizeof(struct dpni_pools_cfg)); - bpool_cfg.num_dpbp = 1; - bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; - bpool_cfg.pools[0].backup_pool = 0; - bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size, - DPAA2_PACKET_LAYOUT_ALIGN); - bpool_cfg.pools[0].priority_mask = 0; - - retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg); - if (retcode != 0) { - DPAA2_PMD_ERR("Error configuring buffer pool on interface." - " bpid = %d error code = %d", - bpool_cfg.pools[0].dpbp_id, retcode); - return retcode; - } - - priv->bp_list = bp_list; - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 5e2011b911..32fab43142 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -73,8 +73,6 @@ static uint64_t dev_tx_offloads_sup = static uint64_t dev_tx_offloads_nodis = RTE_ETH_TX_OFFLOAD_MULTI_SEGS; -bool dpaa2_print_parser_result; - /* Rx descriptor limit when DPNI loads PFDRs in PEB */ #define MAX_NB_RX_DESC_IN_PEB 11264 static int total_nb_rx_desc; @@ -85,27 +83,6 @@ static int total_nb_rx_desc; * patterns are inspected by dpaa2_dev_rss_reta_update(). */ #define DPAA2_RETA_SIZE 64 - -/* Values of dist_size accepted by the DPNI 'dpni_set_rx_hash_dist' MC command. - * Source: fsl_dpni.h, "struct dpni_rx_dist_cfg::dist_size" documentation. - * Used by dpaa2_dev_rss_reta_update() to validate user-requested patterns. - */ -static const uint16_t dpaa2_dist_size_allowed[] = { - 1, 2, 3, 4, 6, 7, 8, 12, 14, 16, 24, 28, 32, 48, 56, 64, - 96, 112, 128, 192, 224, 256, 384, 448, 512, 768, 896, 1024, -}; - -static bool -dpaa2_dist_size_is_supported(uint16_t n) -{ - size_t i; - for (i = 0; i < RTE_DIM(dpaa2_dist_size_allowed); i++) { - if (dpaa2_dist_size_allowed[i] == n) - return true; - } - return false; -} - int dpaa2_valid_dev; struct rte_mempool *dpaa2_tx_sg_pool; @@ -377,6 +354,151 @@ static int dpaa2_dev_link_update(struct rte_eth_dev *dev, static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev); static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev); static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); +static int +dpaa2_setup_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint64_t req_dist_set, int tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + int tc_dist_queues; + struct rte_flow_attr attr; + struct rte_flow_action_rss action_rss; + struct rte_flow_action actions[2]; + struct rte_flow *rss_flow; + + /*TC distribution size is set with dist_queues or + * nb_rx_queues % dist_queues in order of TC priority index. + * Calculating dist size for this tc_index:- + */ + tc_dist_queues = eth_dev->data->nb_rx_queues - + tc_index * priv->dist_queues; + if (tc_dist_queues <= 0) { + DPAA2_PMD_DEBUG("No distribution on TC%d", tc_index); + return 0; + } + + if (tc_dist_queues > priv->dist_queues) + tc_dist_queues = priv->dist_queues; + + memset(&attr, 0, sizeof(attr)); + action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT; + action_rss.level = 0; + action_rss.types = req_dist_set; + action_rss.key_len = 0; + action_rss.key = NULL; + action_rss.queue = NULL; + action_rss.queue_num = tc_dist_queues; + + actions[0].type = RTE_FLOW_ACTION_TYPE_RSS; + actions[0].conf = &action_rss; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + attr.group = tc_index; + attr.ingress = 1; + rss_flow = rte_flow_create(eth_dev->data->port_id, &attr, NULL, actions, NULL); + if (!rss_flow) { + DPAA2_PMD_WARN("%s: Set RSS flow dist on tc%d failed", + __func__, tc_index); + return -EIO; + } + + return 0; +} + +static int +dpaa2_setup_flow_dcb_dist(struct rte_eth_dev *eth_dev, + uint8_t prio, uint8_t tc) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct rte_flow_attr attr; + struct rte_flow_action actions[2]; + struct rte_flow_item_vlan vlan_item; + struct rte_flow_item_vlan vlan_mask; + struct rte_flow_item items[2]; + struct rte_flow_action_jump action_jump; + struct rte_flow *qos_flow; + + memset(&attr, 0, sizeof(struct rte_flow_attr)); + attr.ingress = 1; + + attr.group = priv->num_rx_tc; + attr.priority = prio; + memset(&vlan_item, 0, sizeof(struct rte_flow_item_vlan)); + memset(&vlan_mask, 0, sizeof(struct rte_flow_item_vlan)); + vlan_item.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_TCI_MAKE(0, prio, 0)); + vlan_mask.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_PRI_MASK); + items[0].spec = &vlan_item; + items[0].mask = &vlan_mask; + items[0].type = RTE_FLOW_ITEM_TYPE_VLAN; + items[1].type = RTE_FLOW_ITEM_TYPE_END; + + actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + action_jump.group = tc; + actions[0].conf = &action_jump; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + + qos_flow = rte_flow_create(eth_dev->data->port_id, + &attr, items, actions, NULL); + if (!qos_flow) { + DPAA2_PMD_WARN("Failed to direct vlan with prio(%d) to tc%d", prio, tc); + return -EIO; + } + priv->dcb_flow[prio] = qos_flow; + + return 0; +} + +static int +dpaa2_remove_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint8_t tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile; + int ret; + + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (!tbl_profile->rss_flow || !tbl_profile->is_rss) { + DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed", + eth_dev->data->name, tc_index); + return 0; + } + ret = rte_flow_destroy(eth_dev->data->port_id, tbl_profile->rss_flow, NULL); + if (ret) + return ret; + tbl_profile->rss_flow = NULL; + + return 0; +} + +static int +dpaa2_update_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint64_t req_dist_set, int tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct rte_flow_action_rss action_rss; + struct rte_flow_action actions[2]; + int ret; + + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (!tbl_profile->rss_flow || !tbl_profile->is_rss) { + DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed", + eth_dev->data->name, tc_index); + return 0; + } + action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT; + action_rss.level = 0; + action_rss.types = req_dist_set; + action_rss.key_len = 0; + action_rss.queue_num = tbl_profile->tc_cfg.dist_size; + action_rss.key = NULL; + action_rss.queue = NULL; + actions[0].type = RTE_FLOW_ACTION_TYPE_RSS; + actions[0].conf = &action_rss; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + ret = rte_flow_actions_update(eth_dev->data->port_id, tbl_profile->rss_flow, + actions, NULL); + + return ret; +} static int dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) @@ -594,7 +716,7 @@ dpaa2_dev_info_get(struct rte_eth_dev *dev, dev_rx_offloads_nodis; dev_info->tx_offload_capa = dev_tx_offloads_sup | dev_tx_offloads_nodis; - dev_info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP; + dev_info->dev_capa = 0; dev_info->max_hash_mac_addrs = 0; dev_info->max_vfs = 0; @@ -864,6 +986,28 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) } } +static int +dpaa2_dev_dcb_info(struct rte_eth_dev *dev, + struct rte_eth_dcb_info *dcb_info) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int i; + + if (!priv->nb_dcb_tcs) + return -ENOTSUP; + + memset(dcb_info, 0, sizeof(struct rte_eth_dcb_info)); + dcb_info->nb_tcs = priv->nb_dcb_tcs; + rte_memcpy(dcb_info->prio_tc, priv->prio_dcb_tc, + sizeof(uint8_t) * RTE_ETH_DCB_NUM_USER_PRIORITIES); + for (i = 0; i < dcb_info->nb_tcs; i++) { + dcb_info->tc_queue.tc_rxq[0][i].base = priv->dist_queues * i; + dcb_info->tc_queue.tc_rxq[0][i].nb_queue = priv->dist_queues; + } + + return 0; +} + static int dpaa2_eth_dev_configure(struct rte_eth_dev *dev) { @@ -876,8 +1020,12 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) int rx_l4_csum_offload = false; int tx_l3_csum_offload = false; int tx_l4_csum_offload = false; - int ret, tc_index; - uint32_t max_rx_pktlen; + int ret, tc_index, nb_tcs; + uint32_t max_rx_pktlen, base; + struct rte_eth_rss_conf *rss_conf; + struct rte_eth_dcb_rx_conf *dcb_rx_conf; + struct rte_dpaa2_default_action_conf *def_act_conf; + struct dpaa2_flow_tbl_profile *tbl_profile; PMD_INIT_FUNC_TRACE(); @@ -923,15 +1071,52 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) return -1; } - if (eth_conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) { + rss_conf = ð_conf->rx_adv_conf.rss_conf; + dcb_rx_conf = ð_conf->rx_adv_conf.dcb_rx_conf; + def_act_conf = eth_conf->rxmode.reserved_ptrs[0]; + + for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + base = priv->dist_queues * tc_index; + if (def_act_conf && tc_index < def_act_conf->max_tc) { + if (def_act_conf->default_flows[tc_index] >= priv->dist_queues) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_queue.index = base + + def_act_conf->default_flows[tc_index]; + } + } + } + if (def_act_conf) { + tbl_profile = &priv->flow_profile.qos_profile; + if (def_act_conf->default_tc >= priv->num_rx_tc) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_jump.group = def_act_conf->default_tc; + } + } + + if (eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist(dev, - eth_conf->rx_adv_conf.rss_conf.rss_hf, - tc_index); + ret = dpaa2_setup_flow_rss_dist(dev, rss_conf->rss_hf, tc_index); if (ret) { - DPAA2_PMD_ERR( - "Unable to set flow distribution on tc%d." - "Check queue config", tc_index); + DPAA2_PMD_ERR("RSS dist on tc%d err(%d)", tc_index, ret); + return ret; + } + } + } + + if ((eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_DCB) && priv->qos_entries) { + nb_tcs = dcb_rx_conf->nb_tcs; + for (tc_index = 0; tc_index < nb_tcs; tc_index++) { + if (tc_index >= priv->num_rx_tc) + break; + ret = dpaa2_setup_flow_dcb_dist(dev, dcb_rx_conf->dcb_tc[tc_index], + tc_index); + if (ret) { + DPAA2_PMD_ERR("DCB direct to tc%d err(%d)", tc_index, ret); return ret; } } @@ -1078,7 +1263,6 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, struct dpni_taildrop taildrop; uint8_t qopt = 0; uint16_t flow_id; - uint32_t bpid; int ret; PMD_INIT_FUNC_TRACE(); @@ -1097,18 +1281,6 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, nb_rx_desc); } - if (!priv->bp_list || priv->bp_list->mp != mb_pool) { - if (rte_eal_process_type() != RTE_PROC_PRIMARY) { - ret = rte_dpaa2_bpid_info_init(mb_pool); - if (ret) - return ret; - } - bpid = mempool_to_bpid(mb_pool); - ret = dpaa2_attach_bp_list(priv, dpni, - rte_dpaa2_bpid_info[bpid].bp_list); - if (ret) - return ret; - } dpaa2_q = priv->rx_vq[rx_queue_id]; if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", @@ -1778,6 +1950,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) struct fsl_mc_io *dpni = dev->process_private; int i, ret; struct rte_eth_link link; + struct dpaa2_flow_tbl_profile *tbl_profile; PMD_INIT_FUNC_TRACE(); @@ -1790,7 +1963,9 @@ dpaa2_dev_close(struct rte_eth_dev *dev) } dpaa2_tm_deinit(dev); - dpaa2_flow_clean(dev); + dpaa2_flow_clean(dev, MAX_TCS); + /** No matter dcb flows are created or not, they are destroyed in flow clean.*/ + memset(priv->dcb_flow, 0, sizeof(void *) * RTE_ETH_DCB_NUM_USER_PRIORITIES); /* Clean the device first */ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); if (ret) { @@ -1824,10 +1999,16 @@ dpaa2_dev_close(struct rte_eth_dev *dev) dev->process_private = NULL; rte_free(dpni); - for (i = 0; i < MAX_TCS; i++) - rte_free(priv->extract.tc_extract_param[i]); - - rte_free(priv->extract.qos_extract_param); + for (i = 0; i < (MAX_TCS + 1); i++) { + if (i < MAX_TCS) + tbl_profile = &priv->flow_profile.tc_profile[i]; + else + tbl_profile = &priv->flow_profile.qos_profile; + rte_free(tbl_profile->extract_param); + tbl_profile->extract_param = NULL; + rte_free(tbl_profile->entry_map); + tbl_profile->entry_map = NULL; + } rte_free(priv->cnt_idx_dma_mem); rte_free(priv->cnt_values_dma_mem); @@ -2727,25 +2908,25 @@ dpaa2_dev_rss_hash_update(struct rte_eth_dev *dev, if (rss_conf->rss_hf) { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist(dev, rss_conf->rss_hf, + ret = dpaa2_update_flow_rss_dist(dev, rss_conf->rss_hf, tc_index); - if (ret) { - DPAA2_PMD_ERR("Unable to set flow dist on tc%d", - tc_index); - return ret; - } + if (ret) + break; } } else { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_remove_flow_dist(dev, tc_index); - if (ret) { - DPAA2_PMD_ERR( - "Unable to remove flow dist on tc%d", - tc_index); - return ret; - } + ret = dpaa2_remove_flow_rss_dist(dev, tc_index); + if (ret) + break; } } + if (ret) { + DPAA2_PMD_ERR("%s: %s flow dist on tc%d err(%d)", + data->name, rss_conf->rss_hf ? "set" : "remove", + tc_index, ret); + + return ret; + } eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_conf->rss_hf; return 0; } @@ -2860,23 +3041,34 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, } } - if (!dpaa2_dist_size_is_supported(n)) { - DPAA2_PMD_ERR("dist_size %u not supported by HW. Allowed: " - "1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,...", - n); + /* The requested distribution size cannot exceed the number of + * distribution queues provisioned per TC. Any HW-specific limitation + * on the exact value is enforced later by the rte_flow update. + */ + if (n > priv->dist_queues) { + DPAA2_PMD_ERR("dist_size %u exceeds max distribution queues %u", + n, priv->dist_queues); return -ENOTSUP; } - /* Apply on every configured RX TC, matching rss_hash_update behavior. */ + /* Apply on every configured RX TC, matching rss_hash_update behavior. + * Program the new dist_size into each TC's RSS flow profile and push + * it to the live flow via rte_flow_actions_update(). + */ for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist_size(dev, + struct dpaa2_flow_tbl_profile *tbl_profile = + &priv->flow_profile.tc_profile[tc_index]; + + tbl_profile->tc_cfg.dist_size = n; + ret = dpaa2_update_flow_rss_dist(dev, eth_conf->rx_adv_conf.rss_conf.rss_hf, - tc_index, n); + tc_index); if (ret) { DPAA2_PMD_ERR("Failed to apply dist_size=%u on tc%d (err=%d)", n, tc_index, ret); return ret; } + priv->dist_size_cur[tc_index] = n; } DPAA2_PMD_DEBUG("RETA updated: dist_size now %u on %u TC(s)", @@ -3434,7 +3626,8 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .timesync_adjust_time = dpaa2_timesync_adjust_time, .timesync_read_rx_timestamp = dpaa2_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = dpaa2_timesync_read_tx_timestamp, - .mtr_ops_get = dpaa2_mtr_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, + .get_dcb_info = dpaa2_dev_dcb_info }; /* Populate the mac address from physically available (u-boot/firmware) and/or @@ -3551,7 +3744,9 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) struct dpni_attr attr; struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; struct dpni_buffer_layout layout; - int ret, hw_id, i; + int ret, hw_id, i, entry_num; + struct dpaa2_flow_tbl_profile *tbl_profile; + uint64_t iova; PMD_INIT_FUNC_TRACE(); @@ -3649,8 +3844,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; - priv->default_flow = RTE_MIN(priv->fs_entries, - priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ @@ -3811,27 +4004,51 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) eth_dev->tx_pkt_burst = dpaa2_dev_tx; /* Init fields w.r.t. classification */ - memset(&priv->extract.qos_key_extract, 0, - sizeof(struct dpaa2_key_extract)); - priv->extract.qos_extract_param = rte_zmalloc(NULL, - DPAA2_EXTRACT_PARAM_MAX_SIZE, - RTE_CACHE_LINE_SIZE); - if (!priv->extract.qos_extract_param) { - DPAA2_PMD_ERR("Memory alloc failed"); - goto init_err; - } - - for (i = 0; i < MAX_TCS; i++) { - memset(&priv->extract.tc_key_extract[i], 0, - sizeof(struct dpaa2_key_extract)); - priv->extract.tc_extract_param[i] = rte_zmalloc(NULL, + for (i = 0; i < (MAX_TCS + 1); i++) { + if (i < MAX_TCS) { + tbl_profile = &priv->flow_profile.tc_profile[i]; + entry_num = priv->fs_entries; + } else { + tbl_profile = &priv->flow_profile.qos_profile; + entry_num = priv->qos_entries; + } + memset(tbl_profile, 0, sizeof(struct dpaa2_flow_tbl_profile)); + tbl_profile->extract_param = rte_zmalloc(NULL, DPAA2_EXTRACT_PARAM_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!priv->extract.tc_extract_param[i]) { - DPAA2_PMD_ERR("Memory alloc failed"); + if (!tbl_profile->extract_param) goto init_err; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(tbl_profile->extract_param, + DPAA2_EXTRACT_PARAM_MAX_SIZE); + tbl_profile->default_drop = false; + if (i < MAX_TCS) { + tbl_profile->tc_cfg.dist_size = priv->dist_queues; + tbl_profile->tc_cfg.key_cfg_iova = iova; + tbl_profile->tc_cfg.tc = i; + /** First flow of TC as default flow, otherwise, may be dropped.*/ + tbl_profile->default_queue.index = priv->dist_queues * i; + } else { + tbl_profile->qos_cfg.key_cfg_iova = iova; + tbl_profile->qos_cfg.keep_entries = true; + /** First TC as default TC, otherwise, may be dropped.*/ + tbl_profile->default_jump.group = 0; } + if (!entry_num) + continue; + + tbl_profile->entry_map = rte_zmalloc(NULL, entry_num / 8 + 1, 0); + if (!tbl_profile->entry_map) + goto init_err; + } + + for (i = 0; i < priv->num_rx_tc; i++) { + if (i >= RTE_ETH_DCB_NUM_USER_PRIORITIES) + break; + if (i >= priv->qos_entries) + break; + priv->prio_dcb_tc[i] = i; } + priv->nb_dcb_tcs = i; ret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token, RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index a76e7f9287..312738931f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ @@ -26,6 +26,13 @@ #include "base/dpaa2_hw_dpni_annot.h" #include "dpaa2_parser_decode.h" +#define DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 106) +#define DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV RTE_FSL_MC_REV(10, 39, 106) +#define DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_POLICER_SET_V2_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV DPAA2_POLICER_SET_V2_MC_REV +#define DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV RTE_FSL_MC_REV(10, 39, 109) #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -37,6 +44,10 @@ #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 +#define DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv) \ + container_of((((struct dpaa2_dev_priv *)priv)->eth_dev->device), \ + struct rte_dpaa2_device, device) + #define DPAA2_EXTRACT_PARAM_MAX_SIZE \ RTE_ALIGN(sizeof(struct dpni_ext_set_rx_tc_dist), 256) @@ -256,125 +267,9 @@ struct dpaa2_dyn_rx_protocol_pos { #define DPAA2_FS_FLC_FLOW_OFFSET \ (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) -#define DPAA2_FAPR_SIZE \ - (sizeof(struct dpaa2_annot_hdr) - \ - offsetof(struct dpaa2_annot_hdr, word3)) - -#define DPAA2_PR_NXTHDR_OFFSET 0 - -#define DPAA2_FAFE_PSR_OFFSET 2 -#define DPAA2_FAFE_PSR_SIZE 2 - -#define DPAA2_FAF_PSR_OFFSET 4 -#define DPAA2_FAF_PSR_SIZE 12 - -#define DPAA2_FAF_TOTAL_SIZE \ - (DPAA2_FAFE_PSR_SIZE + DPAA2_FAF_PSR_SIZE) - -/* Just most popular Frame attribute flags (FAF) here.*/ -enum dpaa2_rx_faf_offset { - /* Set by SP start*/ - FAFE_VXLAN_IN_VLAN_FRAM = 0, - FAFE_VXLAN_IN_IPV4_FRAM = 1, - FAFE_VXLAN_IN_IPV6_FRAM = 2, - FAFE_VXLAN_IN_UDP_FRAM = 3, - FAFE_VXLAN_IN_TCP_FRAM = 4, - - FAFE_ECPRI_FRAM = 7, - /* Set by SP end*/ - - FAF_GTP_PRIMED_FRAM = 1 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_PTP_FRAM = 3 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_VXLAN_FRAM = 4 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ETH_FRAM = 10 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_LLC_SNAP_FRAM = 18 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_VLAN_FRAM = 21 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_PPPOE_PPP_FRAM = 25 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_MPLS_FRAM = 27 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ARP_FRAM = 30 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPV4_FRAM = 34 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPV6_FRAM = 42 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IP_FRAM = 48 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IP_FRAG_FRAM = 50 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ICMP_FRAM = 57 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IGMP_FRAM = 58 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_GRE_FRAM = 65 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_UDP_FRAM = 70 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_TCP_FRAM = 72 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_FRAM = 77 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_ESP_FRAM = 78 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_AH_FRAM = 79 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_SCTP_FRAM = 81 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_DCCP_FRAM = 83 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_GTP_FRAM = 87 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ESP_FRAM = 89 + DPAA2_FAFE_PSR_SIZE * 8, -}; - -enum dpaa2_ecpri_fafe_type { - ECPRI_FAFE_TYPE_0 = (8 - FAFE_ECPRI_FRAM), - ECPRI_FAFE_TYPE_1 = (8 - FAFE_ECPRI_FRAM) | (1 << 1), - ECPRI_FAFE_TYPE_2 = (8 - FAFE_ECPRI_FRAM) | (2 << 1), - ECPRI_FAFE_TYPE_3 = (8 - FAFE_ECPRI_FRAM) | (3 << 1), - ECPRI_FAFE_TYPE_4 = (8 - FAFE_ECPRI_FRAM) | (4 << 1), - ECPRI_FAFE_TYPE_5 = (8 - FAFE_ECPRI_FRAM) | (5 << 1), - ECPRI_FAFE_TYPE_6 = (8 - FAFE_ECPRI_FRAM) | (6 << 1), - ECPRI_FAFE_TYPE_7 = (8 - FAFE_ECPRI_FRAM) | (7 << 1) -}; - -#define DPAA2_PR_ETH_OFF_OFFSET 19 -#define DPAA2_PR_TCI_OFF_OFFSET 21 -#define DPAA2_PR_LAST_ETYPE_OFFSET 23 -#define DPAA2_PR_L3_OFF_OFFSET 27 -#define DPAA2_PR_L4_OFF_OFFSET 30 -#define DPAA2_PR_L5_OFF_OFFSET 31 -#define DPAA2_PR_NXTHDR_OFF_OFFSET 34 - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 -struct ipv4_sd_addr_extract_rule { - uint32_t ipv4_src; - uint32_t ipv4_dst; -}; - -struct ipv6_sd_addr_extract_rule { - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; -}; - -struct ipv4_ds_addr_extract_rule { - uint32_t ipv4_dst; - uint32_t ipv4_src; -}; - -struct ipv6_ds_addr_extract_rule { - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; -}; - -union ip_addr_extract_rule { - struct ipv4_sd_addr_extract_rule ipv4_sd_addr; - struct ipv6_sd_addr_extract_rule ipv6_sd_addr; - struct ipv4_ds_addr_extract_rule ipv4_ds_addr; - struct ipv6_ds_addr_extract_rule ipv6_ds_addr; -}; - -union ip_src_addr_extract_rule { - uint32_t ipv4_src; - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; -}; - -union ip_dst_addr_extract_rule { - uint32_t ipv4_dst; - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; -}; - -enum ip_addr_extract_type { - IP_NONE_ADDR_EXTRACT, - IP_SRC_EXTRACT, - IP_DST_EXTRACT, - IP_SRC_DST_EXTRACT, - IP_DST_SRC_EXTRACT -}; +#define DPAA2_IBTH_MAX_EXTRACT_NB 4 enum key_prot_type { /* HW extracts from standard protocol fields*/ @@ -391,9 +286,9 @@ struct key_prot_field { uint32_t key_field; }; -struct dpaa2_raw_region { - uint8_t raw_start; - uint8_t raw_size; +struct dpaa2_ip_addr_extract { + uint32_t field; + uint8_t max_size; }; struct dpaa2_key_profile { @@ -401,35 +296,52 @@ struct dpaa2_key_profile { uint8_t key_offset[DPKG_MAX_NUM_OF_EXTRACTS]; uint8_t key_size[DPKG_MAX_NUM_OF_EXTRACTS]; - enum ip_addr_extract_type ip_addr_type; - uint8_t ip_addr_extract_pos; - uint8_t ip_addr_extract_off; + struct dpaa2_ip_addr_extract ip_addr_extracts[2]; - uint8_t raw_extract_pos; - uint8_t raw_extract_off; - uint8_t raw_extract_num; - - uint8_t l4_src_port_present; - uint8_t l4_src_port_pos; - uint8_t l4_src_port_offset; - uint8_t l4_dst_port_present; - uint8_t l4_dst_port_pos; - uint8_t l4_dst_port_offset; + uint8_t l4_sp_present; + uint8_t l4_sp_extract_idx; + uint8_t l4_sp_key_offset; + uint8_t l4_dp_present; + uint8_t l4_dp_extract_idx; + uint8_t l4_dp_key_offset; struct key_prot_field prot_field[DPKG_MAX_NUM_OF_EXTRACTS]; uint16_t key_max_size; - struct dpaa2_raw_region raw_region; }; -struct dpaa2_key_extract { +struct dpaa2_flow_tbl_profile { struct dpkg_profile_cfg dpkg; struct dpaa2_key_profile key_profile; + uint8_t *extract_param; + int entry_num; + uint8_t *entry_map; + int enabled; + int is_rss; + void *rss_flow; + union { + struct dpni_qos_tbl_cfg qos_cfg; + struct dpni_rx_dist_cfg tc_cfg; + }; + int default_drop; + union { + struct rte_flow_action_jump default_jump; + struct rte_flow_action_queue default_queue; + }; }; -struct extract_s { - struct dpaa2_key_extract qos_key_extract; - struct dpaa2_key_extract tc_key_extract[MAX_TCS]; - uint8_t *qos_extract_param; - uint8_t *tc_extract_param[MAX_TCS]; +struct dpaa2_flow_profile { + struct dpaa2_flow_tbl_profile qos_profile; + struct dpaa2_flow_tbl_profile tc_profile[MAX_TCS]; + /** Meter per TC.*/ + struct dpaa2_dev_meter_profile *tc_mtr_profile[MAX_TCS]; + void *mtr_flow[MAX_TCS]; + void *mempool[MAX_TCS]; + uint8_t bp_idx[MAX_TCS]; +}; + +struct rte_dpaa2_default_action_conf { + uint8_t default_tc; + uint8_t max_tc; + uint16_t default_flows[]; }; struct dpaa2_dev_meter_profile { @@ -493,15 +405,12 @@ struct dpaa2_dev_priv { /** RXQs in same TC share same cgid.*/ uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; - /* Lowest priority FS flow id to receive flow steering miss frames. */ - uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. * Zero means "use default" (= nb_rx_queues clamped to dist_queues). */ uint16_t dist_size_cur[MAX_TCS]; - uint16_t dpni_ver_major; uint16_t dpni_ver_minor; uint32_t speed_capa; @@ -510,7 +419,10 @@ struct dpaa2_dev_priv { uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */ char ep_name[RTE_DEV_NAME_MAX_LEN]; - struct extract_s extract; + struct dpaa2_flow_profile flow_profile; + uint8_t nb_dcb_tcs; + uint8_t prio_dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES]; + void *dcb_flow[RTE_ETH_DCB_NUM_USER_PRIORITIES]; uint16_t ss_offset; uint64_t ss_iova; @@ -530,6 +442,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool enable_bp_flow_ctrl; bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ @@ -549,7 +462,7 @@ struct dpaa2_dev_priv { */ union dpni_statistics pg_xstats[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; - struct dpaa2_dev_flow *curr; + struct dpaa2_generic_flow *cur_flow; LIST_HEAD(, dpaa2_dev_flow) flows; LIST_HEAD(, dpaa2_dev_meter_profile) profiles; LIST_HEAD(, dpaa2_dev_meter_policy) policies; @@ -569,6 +482,12 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +/* Flow dumps are emitted as partial lines built up across several calls, + * so they cannot use the line-oriented RTE_LOG_LINE helpers. Write to the + * EAL log stream instead of stdout. + */ +#define DPAA2_FLOW_DUMP(...) fprintf(rte_log_get_stream(), __VA_ARGS__) + static inline void dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd, const struct rte_mbuf *m) @@ -619,21 +538,270 @@ dpaa2_timestamp_debug(struct dpaa2_dev_priv *priv, prefix, timestamp, ts.tv_sec, ts.tv_nsec); } -int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg); +static inline void +dpaa2_prot_field_string(uint32_t prot, uint32_t field, + char *string, size_t size) +{ + if (prot == NET_PROT_ETH) { + strlcpy(string, "eth", size); + if (field == NH_FLD_ETH_DA) + rte_strlcat(string, ".dst", size); + else if (field == NH_FLD_ETH_SA) + rte_strlcat(string, ".src", size); + else if (field == NH_FLD_ETH_TYPE) + rte_strlcat(string, ".type", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_VLAN) { + strlcpy(string, "vlan", size); + if (field == NH_FLD_VLAN_TCI) + rte_strlcat(string, ".tci", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_IP) { + strlcpy(string, "ip", size); + if (field == NH_FLD_IP_SRC) + rte_strlcat(string, ".src", size); + else if (field == NH_FLD_IP_DST) + rte_strlcat(string, ".dst", size); + else if (field == NH_FLD_IP_PROTO) + rte_strlcat(string, ".proto", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_TCP) { + strlcpy(string, "tcp", size); + if (field == NH_FLD_TCP_PORT_SRC) + rte_strlcat(string, ".src", size); + else if (field == NH_FLD_TCP_PORT_DST) + rte_strlcat(string, ".dst", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_UDP) { + strlcpy(string, "udp", size); + if (field == NH_FLD_UDP_PORT_SRC) + rte_strlcat(string, ".src", size); + else if (field == NH_FLD_UDP_PORT_DST) + rte_strlcat(string, ".dst", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_ICMP) { + strlcpy(string, "icmp", size); + if (field == NH_FLD_ICMP_TYPE) + rte_strlcat(string, ".type", size); + else if (field == NH_FLD_ICMP_CODE) + rte_strlcat(string, ".code", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_SCTP) { + strlcpy(string, "sctp", size); + if (field == NH_FLD_SCTP_PORT_SRC) + rte_strlcat(string, ".src", size); + else if (field == NH_FLD_SCTP_PORT_DST) + rte_strlcat(string, ".dst", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_GRE) { + strlcpy(string, "gre", size); + if (field == NH_FLD_GRE_TYPE) + rte_strlcat(string, ".type", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_GTP) { + strlcpy(string, "gtp", size); + if (field == NH_FLD_GTP_TEID) + rte_strlcat(string, ".teid", size); + else + rte_strlcat(string, ".unknown field", size); + } else if (prot == NET_PROT_IPSEC_ESP) { + strlcpy(string, "esp", size); + if (field == NH_FLD_IPSEC_ESP_SPI) + rte_strlcat(string, ".spi", size); + else if (field == NH_FLD_IPSEC_ESP_SEQUENCE_NUM) + rte_strlcat(string, ".seq", size); + else + rte_strlcat(string, ".unknown field", size); + } else { + snprintf(string, size, "unknown protocol(%d)", prot); + } +} -int dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index); +static inline void +dpaa2_dump_dpkg(const struct dpkg_profile_cfg *dpkg) +{ + int idx; + char string[32]; + const struct dpkg_extract *extract; + enum dpkg_extract_type type; + enum net_prot prot; + uint32_t field; + + for (idx = 0; idx < dpkg->num_extracts; idx++) { + extract = &dpkg->extracts[idx]; + type = extract->type; + if (type == DPKG_EXTRACT_FROM_HDR) { + prot = extract->extract.from_hdr.prot; + field = extract->extract.from_hdr.field; + dpaa2_prot_field_string(prot, field, string, sizeof(string)); + } else if (type == DPKG_EXTRACT_FROM_DATA) { + snprintf(string, sizeof(string), "raw offset/len: %d/%d", + extract->extract.from_data.offset, + extract->extract.from_data.size); + } else if (type == DPKG_EXTRACT_FROM_PARSE) { + snprintf(string, sizeof(string), + "parse offset/len: %d/%d", + extract->extract.from_parse.offset, + extract->extract.from_parse.size); + } + DPAA2_FLOW_DUMP("%s", string); + if ((idx + 1) < dpkg->num_extracts) + DPAA2_FLOW_DUMP(" / "); + else + DPAA2_FLOW_DUMP("\r\n\n"); + } +} + +static inline int +dpaa2_extract_prev_ip_addr_pos(const struct dpaa2_key_profile *profile) +{ + int idx = -ENXIO; + + if (!profile->num) + return -ENXIO; + + for (idx = profile->num - 1; idx >= 0; idx--) { + if (!(profile->prot_field[idx].type == DPAA2_NET_PROT_KEY && + profile->prot_field[idx].prot == NET_PROT_IP && + (profile->prot_field[idx].key_field == NH_FLD_IP_SRC || + profile->prot_field[idx].key_field == NH_FLD_IP_DST))) + break; + } + + if (idx >= 0) + return idx; + return -ENXIO; +} + +static inline int +dpaa2_extract_ip_addr_add(uint32_t field, + struct dpaa2_key_profile *key_profile, uint8_t size, + int *update, int *pos) +{ + struct dpaa2_ip_addr_extract *ip_addr_extracts; + uint8_t i = 0; + uint16_t max_size_save = key_profile->key_max_size; + char log_buf[128]; + + if (field != NH_FLD_IP_SRC && field != NH_FLD_IP_DST) + return -EINVAL; + + max_size_save -= key_profile->ip_addr_extracts[0].max_size; + max_size_save -= key_profile->ip_addr_extracts[1].max_size; + ip_addr_extracts = key_profile->ip_addr_extracts; + while (i < 2) { + if (ip_addr_extracts[i].field == field) { + if (size > ip_addr_extracts[i].max_size) + ip_addr_extracts[i].max_size = size; + break; + } + if (!ip_addr_extracts[i].field) { + ip_addr_extracts[i].field = field; + ip_addr_extracts[i].max_size = size; + if (update) + *update = 1; + break; + } + i++; + } + if (i > 1) { + snprintf(log_buf, sizeof(log_buf), + "field[0](%d)/size[0](%d)/field[1](%d)/size[1](%d)", + ip_addr_extracts[0].field, + ip_addr_extracts[0].max_size, + ip_addr_extracts[1].field, + ip_addr_extracts[1].max_size); + DPAA2_FLOW_DUMP("Invalid IP address extracts:%s\n", + log_buf); + return -EINVAL; + } + + if (pos) + *pos = i; + + max_size_save += key_profile->ip_addr_extracts[0].max_size; + max_size_save += key_profile->ip_addr_extracts[1].max_size; + key_profile->key_max_size = max_size_save; -int dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index, uint16_t dist_size); + return 0; +} -int dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev, - uint8_t tc_index); +static inline uint8_t +dpaa2_profile_insert_no_ipaddr_extract(struct dpaa2_key_profile *profile, + uint8_t size, uint8_t *poffset, int *ppos, + const struct key_prot_field *prot) +{ + uint8_t idx, ip_addr_num = 0, offset; + + if (profile->ip_addr_extracts[0].field && + profile->ip_addr_extracts[1].field) { + idx = profile->num - 2; + ip_addr_num = 2; + } else if (profile->ip_addr_extracts[0].field) { + idx = profile->num - 1; + ip_addr_num = 1; + } else { + idx = profile->num; + } -int dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, - struct fsl_mc_io *dpni, void *blist); + if (idx > 0) + offset = profile->key_offset[idx - 1] + profile->key_size[idx - 1]; + else + offset = 0; + if (idx > 0) { + profile->key_offset[idx] = + profile->key_offset[idx - 1] + profile->key_size[idx - 1]; + } else { + profile->key_offset[idx] = 0; + } + if (ppos) + *ppos = profile->key_offset[idx]; + profile->key_size[idx] = size; + profile->key_max_size += size; + profile->num++; + + if (ip_addr_num > 0) { + memmove(&profile->prot_field[idx + 1], + &profile->prot_field[idx], + sizeof(struct key_prot_field) * ip_addr_num); + } + if (poffset) + *poffset = offset; + + if (prot) { + rte_memcpy(&profile->prot_field[idx], prot, + sizeof(struct key_prot_field)); + } + + return idx; +} + +static inline void +dpaa2_dpkg_insert_extract(struct dpkg_profile_cfg *kg_cfg, + int idx, const struct dpkg_extract *extract) +{ + int i; + + if (idx != kg_cfg->num_extracts) { + /* Not the last extract index, must have IP address extract.*/ + for (i = kg_cfg->num_extracts - 1; i >= idx; i--) { + rte_memcpy(&kg_cfg->extracts[i + 1], + &kg_cfg->extracts[i], sizeof(struct dpkg_extract)); + } + } + + rte_memcpy(&kg_cfg->extracts[idx], extract, sizeof(struct dpkg_extract)); + kg_cfg->num_extracts++; +} __rte_internal int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, int eth_rx_queue_id, @@ -678,7 +846,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, struct rte_mbuf **bufs, uint16_t nb_pkts); void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); -void dpaa2_flow_clean(struct rte_eth_dev *dev); +void dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id); uint16_t dpaa2_dev_tx_conf(void *txq, int drain); void diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 88a639ba89..e52b796a64 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2022 NXP + * Copyright 2018-2026 NXP */ #include <sys/queue.h> @@ -7,6 +7,7 @@ #include <stdio.h> #include <errno.h> #include <stdint.h> +#include <inttypes.h> #include <string.h> #include <unistd.h> #include <stdarg.h> @@ -17,6 +18,7 @@ #include <rte_flow_driver.h> #include <rte_tailq.h> +#include <eal_export.h> #include <fsl_dpni.h> #include <fsl_dpkg.h> @@ -24,7 +26,27 @@ #include <dpaa2_pmd_logs.h> #include "dpaa2_parser_decode.h" -static char *dpaa2_flow_control_log; +#ifndef RTE_DPAA2_ONE_LEVEL_GROUP_FLOW +#define RTE_DPAA2_ONE_LEVEL_GROUP_FLOW 0 +#endif +#ifndef RTE_DPAA2_QOS_GROUP_FLOW +#define RTE_DPAA2_QOS_GROUP_FLOW 1 +#endif +#ifndef RTE_DPAA2_FS_GROUP_FLOW +#define RTE_DPAA2_FS_GROUP_FLOW 2 +#endif + +#ifndef RTE_DPAA2_FLOW_GROUP_TYPE_GET +#define RTE_DPAA2_FLOW_GROUP_TYPE_GET(group) RTE_DPAA2_ONE_LEVEL_GROUP_FLOW +#endif + +#ifndef RTE_DPAA2_FLOW_GROUP_ID_GET +#define RTE_DPAA2_FLOW_GROUP_ID_GET(group) (group) +#endif + +static bool dpaa2_flow_control_log; + +#define DPAA2_FLOW_QOS_GROUP_ID 0xff /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -35,31 +57,60 @@ enum dpaa2_flow_entry_size { }; enum dpaa2_flow_dist_type { - DPAA2_FLOW_QOS_TYPE = 1 << 0, - DPAA2_FLOW_FS_TYPE = 1 << 1 + DPAA2_FLOW_NULL_TYPE, + DPAA2_FLOW_QOS_TYPE, + DPAA2_FLOW_FS_TYPE }; #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 -#define DPAA2_PROT_FIELD_STRING_SIZE 16 + #define VXLAN_HF_VNI 0x08 +#define DPAA2_MAX_ACTION_PER_FLOW_NUM 4 -struct dpaa2_dev_flow { - LIST_ENTRY(dpaa2_dev_flow) next; - struct dpni_rule_cfg qos_rule; - uint8_t *qos_key_addr; - uint8_t *qos_mask_addr; - uint16_t qos_rule_size; - struct dpni_rule_cfg fs_rule; - uint8_t qos_real_key_size; - uint8_t fs_real_key_size; - uint8_t *fs_key_addr; - uint8_t *fs_mask_addr; - uint16_t fs_rule_size; - uint8_t tc_id; /** Traffic Class ID. */ - uint8_t tc_index; /** index within this Traffic Class. */ +struct dpaa2_dev_flow_qos_action { + enum rte_flow_action_type action_jump_type; + struct rte_flow_action_jump action_jump_cfg; +}; + +struct dpaa2_dev_flow_fs_action { enum rte_flow_action_type action_type; struct dpni_fs_action_cfg fs_action_cfg; + char dst_name[DPNI_FS_REDIR_MAX_NUM][RTE_ETH_NAME_MAX_LEN]; +}; + +union dpaa2_dev_flow_action { + struct dpaa2_dev_flow_qos_action qos_action; + struct dpaa2_dev_flow_fs_action fs_action; +}; + +struct dpaa2_generic_flow { + struct dpni_rule_cfg rule_cfg; + uint8_t *key_addr; + uint8_t *mask_addr; + uint16_t rule_size; + uint16_t entry_index; + /** This flow has IPv4 or IPv6 extracts.*/ + enum net_prot ip_key; + /** This flow has IPv4 or IPv6 source extract.*/ + enum net_prot ip_src; + /** This flow has IPv4 or IPv6 destination extract.*/ + enum net_prot ip_dst; + struct dpaa2_dev_priv *priv; + union { + uint8_t tc_id; /** For FS flow only.*/ + uint8_t flow_id; /** For QoS flow with direct_queue.*/ + }; + union dpaa2_dev_flow_action flow_action; + int is_rss; + int direct_queue; +}; + +struct dpaa2_dev_flow { + LIST_ENTRY(dpaa2_dev_flow) next; + struct dpaa2_generic_flow *qos_flow; + struct dpaa2_generic_flow *fs_flow; + struct dpaa2_dev_priv *priv; }; struct rte_dpaa2_flow_item { @@ -82,20 +133,17 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, - RTE_FLOW_ITEM_TYPE_MPLS, - RTE_FLOW_ITEM_TYPE_PPPOES, - RTE_FLOW_ITEM_TYPE_RAW + RTE_FLOW_ITEM_TYPE_RAW, + /** Hardware parser supports vlan protocol only.*/ + RTE_FLOW_ITEM_TYPE_VXLAN }; static const enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, RTE_FLOW_ITEM_TYPE_ECPRI }; -static const -enum rte_flow_action_type dpaa2_supported_action_type[] = { - RTE_FLOW_ACTION_TYPE_END, +static const enum rte_flow_action_type dpaa2_supported_fs_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, @@ -103,21 +151,47 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_DROP }; +static const enum rte_flow_action_type dpaa2_supported_qos_action_type[] = { + RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_JUMP, + RTE_FLOW_ACTION_TYPE_DROP +}; + + +#define DPAA2_FLOW_HDR_HEX_DUMP_SIZE \ + (RTE_MAX(sizeof(struct rte_flow_item_eth), \ + RTE_MAX(sizeof(struct rte_flow_item_vlan), \ + RTE_MAX(sizeof(struct rte_flow_item_ipv4), \ + RTE_MAX(sizeof(struct rte_flow_item_ipv6), \ + RTE_MAX(sizeof(struct rte_flow_item_icmp), \ + RTE_MAX(sizeof(struct rte_flow_item_udp), \ + RTE_MAX(sizeof(struct rte_flow_item_tcp), \ + RTE_MAX(sizeof(struct rte_flow_item_sctp), \ + RTE_MAX(sizeof(struct rte_flow_item_gre), \ + RTE_MAX(sizeof(struct rte_flow_item_ah), \ + RTE_MAX(sizeof(struct rte_flow_item_esp), \ + RTE_MAX(sizeof(struct rte_flow_item_vxlan), \ + RTE_MAX(sizeof(struct rte_flow_item_ecpri), \ + sizeof(struct rte_flow_item_gtp)))))))))))))) * 10) + + #ifndef __cplusplus static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = { - .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - .hdr.ether_type = RTE_BE16(0xffff), + .dst.addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .src.addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .type = RTE_BE16(0xffff), }; static const struct rte_flow_item_vlan dpaa2_flow_item_vlan_mask = { - .hdr.vlan_tci = RTE_BE16(0xffff), + .tci = RTE_BE16(0xffff), }; static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = { .hdr.src_addr = RTE_BE32(0xffffffff), .hdr.dst_addr = RTE_BE32(0xffffffff), .hdr.next_proto_id = 0xff, + .hdr.packet_id = 0xffff, + .hdr.fragment_offset = 0xffff, }; static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = { @@ -171,9 +245,10 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, + .vni = {0xff, 0xff, 0xff}, }; + static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { .hdr.common.type = 0xff, .hdr.dummy[0] = RTE_BE32(0xffffffff), @@ -185,253 +260,201 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; -static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { - .label_tc_s = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { - .session_id = RTE_BE16(0xffff), -}; - #endif +static inline uint8_t +dpaa2_flow_entry_map_get(const uint8_t *entry_map, + uint16_t index) +{ + uint16_t byte_pos = index / 8; + uint16_t bit_pos = index % 8; -#define DPAA2_FLOW_DUMP printf + return entry_map[byte_pos] & (1 << bit_pos); +} static inline void -dpaa2_prot_field_string(uint32_t prot, uint32_t field, - char *string) +dpaa2_flow_entry_map_set(uint8_t *entry_map, + uint16_t index, int set) { - if (!dpaa2_flow_control_log) - return; + uint16_t byte_pos = index / 8; + uint16_t bit_pos = index % 8; - if (prot == NET_PROT_ETH) { - strcpy(string, "eth"); - if (field == NH_FLD_ETH_DA) - strcat(string, ".dst"); - else if (field == NH_FLD_ETH_SA) - strcat(string, ".src"); - else if (field == NH_FLD_ETH_TYPE) - strcat(string, ".type"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_VLAN) { - strcpy(string, "vlan"); - if (field == NH_FLD_VLAN_TCI) - strcat(string, ".tci"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_IP) { - strcpy(string, "ip"); - if (field == NH_FLD_IP_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_IP_DST) - strcat(string, ".dst"); - else if (field == NH_FLD_IP_PROTO) - strcat(string, ".proto"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_TCP) { - strcpy(string, "tcp"); - if (field == NH_FLD_TCP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_TCP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_UDP) { - strcpy(string, "udp"); - if (field == NH_FLD_UDP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_UDP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_ICMP) { - strcpy(string, "icmp"); - if (field == NH_FLD_ICMP_TYPE) - strcat(string, ".type"); - else if (field == NH_FLD_ICMP_CODE) - strcat(string, ".code"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_SCTP) { - strcpy(string, "sctp"); - if (field == NH_FLD_SCTP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_SCTP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_GRE) { - strcpy(string, "gre"); - if (field == NH_FLD_GRE_TYPE) - strcat(string, ".type"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_GTP) { - rte_strscpy(string, "gtp", DPAA2_PROT_FIELD_STRING_SIZE); - if (field == NH_FLD_GTP_TEID) - strcat(string, ".teid"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_IPSEC_ESP) { - rte_strscpy(string, "esp", DPAA2_PROT_FIELD_STRING_SIZE); - if (field == NH_FLD_IPSEC_ESP_SPI) - strcat(string, ".spi"); - else if (field == NH_FLD_IPSEC_ESP_SEQUENCE_NUM) - strcat(string, ".seq"); - else - strcat(string, ".unknown field"); - } else { - sprintf(string, "unknown protocol(%d)", prot); - } + if (set) + entry_map[byte_pos] |= (1 << bit_pos); + else + entry_map[byte_pos] &= ~(((uint8_t)1) << bit_pos); } +/* Append formatted text to a fixed-size buffer at *off and advance *off. + * snprintf() returns the length it *would* have written, so clamp the + * offset to keep it inside the buffer when the output is truncated. + */ +#define DPAA2_FLOW_STR_APPEND(buf, off, ...) \ +do { \ + int _len = snprintf(&(buf)[(off)], sizeof(buf) - (off), __VA_ARGS__); \ + if (_len > 0) { \ + (off) += _len; \ + if ((size_t)(off) >= sizeof(buf)) \ + (off) = sizeof(buf) - 1; \ + } \ +} while (0) + static inline void -dpaa2_flow_qos_extracts_log(const struct dpaa2_dev_priv *priv) +dpaa2_flow_extracts_log(const struct dpaa2_dev_priv *priv, + const char *prefix, uint8_t tc_id) { - int idx; - char string[32]; - const struct dpkg_profile_cfg *dpkg = - &priv->extract.qos_key_extract.dpkg; - const struct dpkg_extract *extract; - enum dpkg_extract_type type; - enum net_prot prot; - uint32_t field; + char string[1024]; + const struct dpaa2_flow_tbl_profile *tbl_profile; + int offset = 0; if (!dpaa2_flow_control_log) return; - DPAA2_FLOW_DUMP("QoS table: %d extracts\r\n", - dpkg->num_extracts); - for (idx = 0; idx < dpkg->num_extracts; idx++) { - extract = &dpkg->extracts[idx]; - type = extract->type; - if (type == DPKG_EXTRACT_FROM_HDR) { - prot = extract->extract.from_hdr.prot; - field = extract->extract.from_hdr.field; - dpaa2_prot_field_string(prot, field, - string); - } else if (type == DPKG_EXTRACT_FROM_DATA) { - sprintf(string, "raw offset/len: %d/%d", - extract->extract.from_data.offset, - extract->extract.from_data.size); - } else if (type == DPKG_EXTRACT_FROM_PARSE) { - sprintf(string, "parse offset/len: %d/%d", - extract->extract.from_parse.offset, - extract->extract.from_parse.size); - } - DPAA2_FLOW_DUMP("%s", string); - if ((idx + 1) < dpkg->num_extracts) - DPAA2_FLOW_DUMP(" / "); - } - DPAA2_FLOW_DUMP("\r\n"); + DPAA2_FLOW_STR_APPEND(string, offset, + "%s's", priv->eth_dev->data->name); + if (tc_id >= MAX_TCS) { + tbl_profile = &priv->flow_profile.qos_profile; + DPAA2_FLOW_STR_APPEND(string, offset, + " QoS"); + } else { + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + DPAA2_FLOW_STR_APPEND(string, offset, + " FS[%d]", tc_id); + } + DPAA2_FLOW_STR_APPEND(string, offset, + " table: %d extracts/%d entries\n", tbl_profile->dpkg.num_extracts, tbl_profile->entry_num); + DPAA2_FLOW_DUMP("\n%s %s", prefix, string); + dpaa2_dump_dpkg(&tbl_profile->dpkg); } static inline void -dpaa2_flow_fs_extracts_log(const struct dpaa2_dev_priv *priv, - int tc_id) +dpaa2_flow_qos_entry_log(const char *log_info, + const struct dpaa2_generic_flow *flow) { int idx; - char string[32]; - const struct dpkg_profile_cfg *dpkg = - &priv->extract.tc_key_extract[tc_id].dpkg; - const struct dpkg_extract *extract; - enum dpkg_extract_type type; - enum net_prot prot; - uint32_t field; + struct rte_eth_dev *dev = flow->priv->eth_dev; if (!dpaa2_flow_control_log) return; - DPAA2_FLOW_DUMP("FS table: %d extracts in TC[%d]\r\n", - dpkg->num_extracts, tc_id); - for (idx = 0; idx < dpkg->num_extracts; idx++) { - extract = &dpkg->extracts[idx]; - type = extract->type; - if (type == DPKG_EXTRACT_FROM_HDR) { - prot = extract->extract.from_hdr.prot; - field = extract->extract.from_hdr.field; - dpaa2_prot_field_string(prot, field, - string); - } else if (type == DPKG_EXTRACT_FROM_DATA) { - sprintf(string, "raw offset/len: %d/%d", - extract->extract.from_data.offset, - extract->extract.from_data.size); - } else if (type == DPKG_EXTRACT_FROM_PARSE) { - sprintf(string, "parse offset/len: %d/%d", - extract->extract.from_parse.offset, - extract->extract.from_parse.size); - } - DPAA2_FLOW_DUMP("%s", string); - if ((idx + 1) < dpkg->num_extracts) - DPAA2_FLOW_DUMP(" / "); - } - DPAA2_FLOW_DUMP("\r\n"); + DPAA2_FLOW_DUMP("%s: %s QoS entry[%d](size %d/%d) to select TC[%d]\n", + dev->data->name, log_info, flow->entry_index, flow->rule_size, + flow->rule_cfg.key_size, + flow->flow_action.qos_action.action_jump_cfg.group); + + DPAA2_FLOW_DUMP("key:\r\n"); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->key_addr[idx]); + + DPAA2_FLOW_DUMP("\r\nmask:\r\n"); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->mask_addr[idx]); + DPAA2_FLOW_DUMP("\r\n\n"); } static inline void -dpaa2_flow_qos_entry_log(const char *log_info, - const struct dpaa2_dev_flow *flow, int qos_index) +dpaa2_flow_fs_entry_log(const char *log_info, + const struct dpaa2_generic_flow *flow) { int idx; - uint8_t *key, *mask; + struct rte_eth_dev *dev = flow->priv->eth_dev; + const struct dpaa2_dev_flow_fs_action *fs_action; if (!dpaa2_flow_control_log) return; - if (qos_index >= 0) { - DPAA2_FLOW_DUMP("%s QoS entry[%d](size %d/%d) for TC[%d]\r\n", - log_info, qos_index, flow->qos_rule_size, - flow->qos_rule.key_size, - flow->tc_id); - } else { - DPAA2_FLOW_DUMP("%s QoS entry(size %d/%d) for TC[%d]\r\n", - log_info, flow->qos_rule_size, - flow->qos_rule.key_size, - flow->tc_id); - } + DPAA2_FLOW_DUMP("%s: %s FS[%d]/entry[%d](size %d/%d)\r\n", + dev->data->name, log_info, flow->tc_id, + flow->entry_index, flow->rule_size, + flow->rule_cfg.key_size); - key = flow->qos_key_addr; - mask = flow->qos_mask_addr; + fs_action = &flow->flow_action.fs_action; DPAA2_FLOW_DUMP("key:\r\n"); - for (idx = 0; idx < flow->qos_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", key[idx]); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->key_addr[idx]); DPAA2_FLOW_DUMP("\r\nmask:\r\n"); - for (idx = 0; idx < flow->qos_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", mask[idx]); - DPAA2_FLOW_DUMP("\r\n"); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->mask_addr[idx]); + DPAA2_FLOW_DUMP("\r\nAction: "); + if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { + DPAA2_FLOW_DUMP("Receive to flow%d\r\n\n", + fs_action->fs_action_cfg.flow_id); + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || + fs_action->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { + DPAA2_FLOW_DUMP("Re-direct to port(s): "); + for (idx = 0; idx < fs_action->fs_action_cfg.num_tokens; idx++) { + DPAA2_FLOW_DUMP("%s", fs_action->dst_name[idx]); + if ((idx + 1) < fs_action->fs_action_cfg.num_tokens) + DPAA2_FLOW_DUMP(", "); + } + DPAA2_FLOW_DUMP("\r\n"); + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + DPAA2_FLOW_DUMP("Drop\r\n\n"); + } else { + DPAA2_FLOW_DUMP("Un-supported action type(%d)\r\n\n", + fs_action->action_type); + } } static inline void -dpaa2_flow_fs_entry_log(const char *log_info, - const struct dpaa2_dev_flow *flow) +dpaa2_dump_extract_map(const struct dpaa2_dev_priv *priv, + const char *prefix, enum dpaa2_flow_dist_type dist_type, + uint8_t group) { - int idx; - uint8_t *key, *mask; + int idx, offset = 0; + char string[2048]; + const struct dpaa2_flow_tbl_profile *tbl_profile; if (!dpaa2_flow_control_log) return; - DPAA2_FLOW_DUMP("%s FS/TC entry[%d](size %d/%d) of TC[%d]\r\n", - log_info, flow->tc_index, - flow->fs_rule_size, flow->fs_rule.key_size, - flow->tc_id); + DPAA2_FLOW_DUMP("%s: %s\n", priv->eth_dev->data->name, prefix); - key = flow->fs_key_addr; - mask = flow->fs_mask_addr; + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + DPAA2_FLOW_STR_APPEND(string, offset, + "QoS entry map:"); + if (!tbl_profile->entry_num) { + DPAA2_FLOW_STR_APPEND(string, offset, + " empty\n"); + goto qos_dump_end; + } else { + DPAA2_FLOW_STR_APPEND(string, offset, + "\n"); + } + for (idx = 0; idx < priv->qos_entries; idx++) { + DPAA2_FLOW_STR_APPEND(string, offset, + "%d ", dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx) ? 1 : 0); + if (!((idx + 1) % 16) || (idx + 1) == priv->qos_entries) + DPAA2_FLOW_STR_APPEND(string, offset, + "\n"); + } - DPAA2_FLOW_DUMP("key:\r\n"); - for (idx = 0; idx < flow->fs_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", key[idx]); +qos_dump_end: + DPAA2_FLOW_DUMP("%s\n", string); - DPAA2_FLOW_DUMP("\r\nmask:\r\n"); - for (idx = 0; idx < flow->fs_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", mask[idx]); - DPAA2_FLOW_DUMP("\r\n"); + return; + } + + tbl_profile = &priv->flow_profile.tc_profile[group]; + if (!tbl_profile->entry_num) { + DPAA2_FLOW_DUMP("FS[%d] table is empty\n\n", group); + return; + } + + offset = 0; + DPAA2_FLOW_STR_APPEND(string, offset, + "FS[%d] %d entries:\n", group, tbl_profile->entry_num); + for (idx = 0; idx < priv->fs_entries; idx++) { + DPAA2_FLOW_STR_APPEND(string, offset, + "%d ", dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx) ? 1 : 0); + if (!((idx + 1) % 16) || (idx + 1) == priv->fs_entries) + DPAA2_FLOW_STR_APPEND(string, offset, + "\n"); + } + DPAA2_FLOW_DUMP("%s\n", string); } static int @@ -488,272 +511,481 @@ dpaa2_flow_l4_dst_port_extract(enum net_prot prot, return false; } +static int +dpaa2_flow_rss_conf_to_item(uint64_t req_dist_set, + struct rte_flow_item *items, uint8_t *spec_buf, + uint32_t buf_max) +{ + uint32_t i = 0, offset = 0; + uint64_t l2_mask, vlan_mask, ipv4_mask, ipv6_mask; + uint64_t dist_supported, udp_mask, tcp_mask, sctp_mask; + struct rte_flow_item_eth *eth = NULL; + struct rte_flow_item_pppoe *pppoe = NULL; + struct rte_flow_item_esp *esp = NULL; + struct rte_flow_item_ah *ah = NULL; + struct rte_flow_item_vlan *vlan = NULL; + struct rte_flow_item_mpls *mpls = NULL; + struct rte_flow_item_gtp *gtpu = NULL; + struct rte_flow_item_udp *udp = NULL; + struct rte_flow_item_tcp *tcp = NULL; + struct rte_flow_item_sctp *sctp = NULL; + struct rte_flow_item_ipv4 *ipv4 = NULL; + + l2_mask = RTE_ETH_RSS_L2_PAYLOAD | RTE_ETH_RSS_ETH; + vlan_mask = RTE_ETH_RSS_C_VLAN | RTE_ETH_RSS_S_VLAN; + ipv4_mask = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | + RTE_ETH_RSS_NONFRAG_IPV4_OTHER; + ipv6_mask = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | + RTE_ETH_RSS_IPV6_EX | RTE_ETH_RSS_NONFRAG_IPV6_OTHER; + udp_mask = RTE_ETH_RSS_NONFRAG_IPV4_UDP | + RTE_ETH_RSS_NONFRAG_IPV6_UDP | + RTE_ETH_RSS_IPV6_UDP_EX; + tcp_mask = RTE_ETH_RSS_NONFRAG_IPV4_TCP | + RTE_ETH_RSS_NONFRAG_IPV6_TCP | + RTE_ETH_RSS_IPV6_TCP_EX; + sctp_mask = RTE_ETH_RSS_NONFRAG_IPV4_SCTP | + RTE_ETH_RSS_NONFRAG_IPV6_SCTP; + dist_supported = l2_mask | vlan_mask | ipv4_mask | + ipv6_mask | udp_mask | tcp_mask | sctp_mask | + RTE_ETH_RSS_GTPU | RTE_ETH_RSS_PPPOE | + RTE_ETH_RSS_ESP | RTE_ETH_RSS_AH | RTE_ETH_RSS_MPLS; + if (~dist_supported & req_dist_set) { + DPAA2_PMD_ERR("%s: Unsupported dist type:0x%" PRIx64, + __func__, (~dist_supported) & req_dist_set); + return -ENOTSUP; + } + + if (req_dist_set & l2_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_ETH; + eth = (void *)(spec_buf + offset); + memset(eth, 0, sizeof(struct rte_flow_item_eth)); + memset(eth->dst.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN); + memset(eth->src.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN); + eth->type = RTE_BE16(0xffff); + items[i].spec = eth; + items[i].mask = eth; + i++; + offset += sizeof(struct rte_flow_item_eth); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_PPPOE) { + items[i].type = RTE_FLOW_ITEM_TYPE_PPPOES; + pppoe = (void *)(spec_buf + offset); + memset(pppoe, 0, sizeof(struct rte_flow_item_pppoe)); + pppoe->session_id = RTE_BE16(0xffff); + items[i].spec = pppoe; + items[i].mask = pppoe; + i++; + offset += sizeof(struct rte_flow_item_pppoe); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_ESP) { + items[i].type = RTE_FLOW_ITEM_TYPE_ESP; + esp = (void *)(spec_buf + offset); + memset(esp, 0, sizeof(struct rte_flow_item_esp)); + esp->hdr.spi = RTE_BE32(0xffffffff); + items[i].spec = esp; + items[i].mask = esp; + i++; + offset += sizeof(struct rte_flow_item_esp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_AH) { + items[i].type = RTE_FLOW_ITEM_TYPE_AH; + ah = (void *)(spec_buf + offset); + memset(ah, 0, sizeof(struct rte_flow_item_ah)); + ah->spi = RTE_BE32(0xffffffff); + items[i].spec = ah; + items[i].mask = ah; + i++; + offset += sizeof(struct rte_flow_item_ah); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & vlan_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_VLAN; + vlan = (void *)(spec_buf + offset); + memset(vlan, 0, sizeof(struct rte_flow_item_vlan)); + vlan->tci = RTE_BE16(0xffff); + items[i].spec = vlan; + items[i].mask = vlan; + i++; + offset += sizeof(struct rte_flow_item_vlan); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_MPLS) { + items[i].type = RTE_FLOW_ITEM_TYPE_MPLS; + mpls = (void *)(spec_buf + offset); + memset(mpls, 0, sizeof(struct rte_flow_item_mpls)); + memset(mpls->label_tc_s, 0xff, 3); + items[i].spec = mpls; + items[i].mask = mpls; + i++; + offset += sizeof(struct rte_flow_item_mpls); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_GTPU) { + items[i].type = RTE_FLOW_ITEM_TYPE_GTPU; + gtpu = (void *)(spec_buf + offset); + memset(gtpu, 0, sizeof(struct rte_flow_item_gtp)); + gtpu->teid = RTE_BE32(0xffffffff); + items[i].spec = gtpu; + items[i].mask = gtpu; + i++; + offset += sizeof(struct rte_flow_item_gtp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & udp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_UDP; + udp = (void *)(spec_buf + offset); + memset(udp, 0, sizeof(struct rte_flow_item_udp)); + udp->hdr.src_port = RTE_BE16(0xffff); + udp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = udp; + items[i].mask = udp; + i++; + offset += sizeof(struct rte_flow_item_udp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & tcp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_TCP; + tcp = (void *)(spec_buf + offset); + memset(tcp, 0, sizeof(struct rte_flow_item_tcp)); + tcp->hdr.src_port = RTE_BE16(0xffff); + tcp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = tcp; + items[i].mask = tcp; + i++; + offset += sizeof(struct rte_flow_item_tcp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & sctp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_SCTP; + sctp = (void *)(spec_buf + offset); + memset(sctp, 0, sizeof(struct rte_flow_item_sctp)); + sctp->hdr.src_port = RTE_BE16(0xffff); + sctp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = sctp; + items[i].mask = sctp; + i++; + offset += sizeof(struct rte_flow_item_sctp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & ipv4_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_IPV4; + ipv4 = (void *)(spec_buf + offset); + memset(ipv4, 0, sizeof(struct rte_flow_item_ipv4)); + ipv4->hdr.src_addr = RTE_BE32(0xffffffff); + ipv4->hdr.dst_addr = RTE_BE32(0xffffffff); + ipv4->hdr.next_proto_id = 0xff; + items[i].spec = ipv4; + items[i].mask = ipv4; + i++; + offset += sizeof(struct rte_flow_item_ipv4); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + items[i].type = RTE_FLOW_ITEM_TYPE_END; + + return i; +} + static int dpaa2_flow_add_qos_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow) + struct dpaa2_generic_flow *flow) { - uint16_t qos_index; + struct dpaa2_flow_tbl_profile *tbl_profile; int ret; struct fsl_mc_io *dpni = priv->hw; + uint8_t flags = DPNI_QOS_OPT_SET_TC_ONLY, flow_id = 0; - if (priv->num_rx_tc <= 1 && - flow->action_type != RTE_FLOW_ACTION_TYPE_RSS) { - DPAA2_PMD_WARN("No QoS Table for FS"); + if (flow->entry_index >= priv->qos_entries) { + DPAA2_PMD_ERR("QoS table full(%d >= %d)", + flow->entry_index, priv->qos_entries); + return -EINVAL; + } + tbl_profile = &priv->flow_profile.qos_profile; + if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, + flow->entry_index)) { + DPAA2_PMD_ERR("QoS entry[%d] has been occupied", + flow->entry_index); return -EINVAL; } - /* QoS entry added is only effective for multiple TCs.*/ - qos_index = flow->tc_id * priv->fs_entries + flow->tc_index; - if (qos_index >= priv->qos_entries) { - DPAA2_PMD_ERR("QoS table full(%d >= %d)", - qos_index, priv->qos_entries); + if (flow->flow_action.qos_action.action_jump_type != + RTE_FLOW_ACTION_TYPE_JUMP) { + DPAA2_PMD_ERR("QoS entry[%d]'jump action not set(%d)", + flow->entry_index, + flow->flow_action.qos_action.action_jump_type); + return -EINVAL; + } + if (flow->flow_action.qos_action.action_jump_cfg.group >= + priv->num_rx_tc) { + DPAA2_PMD_ERR("QoS entry[%d]'dest table ID(%d) >= max(%d)", + flow->entry_index, + flow->flow_action.qos_action.action_jump_cfg.group, + priv->num_rx_tc); return -EINVAL; } - dpaa2_flow_qos_entry_log("Start add", flow, qos_index); + dpaa2_flow_qos_entry_log("Add", flow); + if (flow->direct_queue) { + flags |= DPNI_QOS_OPT_SET_FLOW_ID; + flow_id = flow->flow_id; + } ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, - priv->token, &flow->qos_rule, - flow->tc_id, qos_index, - 0, 0); + priv->token, &flow->rule_cfg, + flow->flow_action.qos_action.action_jump_cfg.group, + flow->entry_index, flags, flow_id); if (ret < 0) { DPAA2_PMD_ERR("Add entry(%d) to table(%d) failed", - qos_index, flow->tc_id); + flow->entry_index, + flow->flow_action.qos_action.action_jump_cfg.group); return ret; } + dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 1); + tbl_profile->entry_num++; return 0; } static int dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow) + struct dpaa2_generic_flow *flow) { + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_flow_tbl_profile *tbl_profile; int ret; struct fsl_mc_io *dpni = priv->hw; - if (flow->tc_index >= priv->fs_entries) { - DPAA2_PMD_ERR("FS table full(%d >= %d)", - flow->tc_index, priv->fs_entries); + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + tbl_profile = &priv->flow_profile.tc_profile[flow->tc_id]; + if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, + flow->entry_index)) { + DPAA2_PMD_ERR("FS[%d].entry[%d] has been occupied", + flow->tc_id, flow->entry_index); return -EINVAL; } - dpaa2_flow_fs_entry_log("Start add", flow); + dpaa2_flow_fs_entry_log("Add", flow); - ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, - priv->token, flow->tc_id, - flow->tc_index, &flow->fs_rule, - &flow->fs_action_cfg); + if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { + ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg); + } else { + ret = dpni_add_fs_entry_legacy(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg); + } if (ret < 0) { DPAA2_PMD_ERR("Add rule(%d) to FS table(%d) failed", - flow->tc_index, flow->tc_id); + flow->entry_index, flow->tc_id); return ret; } + dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 1); + tbl_profile->entry_num++; + return 0; } static int -dpaa2_flow_rule_insert_hole(struct dpaa2_dev_flow *flow, - int offset, int size, - enum dpaa2_flow_dist_type dist_type) +dpaa2_flow_update_qos_rule_action(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow) { - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - if (offset < flow->qos_rule_size) { - memmove(flow->qos_key_addr + offset + size, - flow->qos_key_addr + offset, - flow->qos_rule_size - offset); - memset(flow->qos_key_addr + offset, - 0, size); - - memmove(flow->qos_mask_addr + offset + size, - flow->qos_mask_addr + offset, - flow->qos_rule_size - offset); - memset(flow->qos_mask_addr + offset, - 0, size); - flow->qos_rule_size += size; - } else { - flow->qos_rule_size = offset + size; - } + int ret; + struct fsl_mc_io *dpni = priv->hw; + uint8_t flags = DPNI_QOS_OPT_UPDATE_IF_EXISTS, flow_id = 0; + + dpaa2_flow_qos_entry_log("Update action", flow); + + if (flow->direct_queue) { + flags |= DPNI_QOS_OPT_SET_FLOW_ID; + flow_id = flow->flow_id; } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - if (offset < flow->fs_rule_size) { - memmove(flow->fs_key_addr + offset + size, - flow->fs_key_addr + offset, - flow->fs_rule_size - offset); - memset(flow->fs_key_addr + offset, - 0, size); - - memmove(flow->fs_mask_addr + offset + size, - flow->fs_mask_addr + offset, - flow->fs_rule_size - offset); - memset(flow->fs_mask_addr + offset, - 0, size); - flow->fs_rule_size += size; - } else { - flow->fs_rule_size = offset + size; - } + /** This option doesn't support legacy operation.*/ + ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, + priv->token, &flow->rule_cfg, + flow->flow_action.qos_action.action_jump_cfg.group, + flow->entry_index, + flags, flow_id); + if (ret < 0) { + DPAA2_PMD_ERR("Update rule(%d) in QOS table failed(%d)", + flow->entry_index, ret); + return ret; } return 0; } static int -dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv, - enum dpaa2_flow_dist_type dist_type, - uint16_t entry_size, uint8_t tc_id) +dpaa2_flow_update_fs_rule_action(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow) { - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); int ret; + struct fsl_mc_io *dpni = priv->hw; + struct dpni_fs_action_cfg *cfg; - while (curr) { - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - if (priv->num_rx_tc > 1 || - curr->action_type == - RTE_FLOW_ACTION_TYPE_RSS) { - curr->qos_rule.key_size = entry_size; - ret = dpaa2_flow_add_qos_rule(priv, curr); - if (ret) - return ret; - } - } - if (dist_type & DPAA2_FLOW_FS_TYPE && - curr->tc_id == tc_id) { - curr->fs_rule.key_size = entry_size; - ret = dpaa2_flow_add_fs_rule(priv, curr); - if (ret) - return ret; - } - curr = LIST_NEXT(curr, next); + dpaa2_flow_fs_entry_log("Update action", flow); + + cfg = &flow->flow_action.fs_action.fs_action_cfg; + cfg->options |= DPNI_FS_OPT_UPDATE_IF_EXISTS; + /** This option doesn't support legacy operation.*/ + ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, cfg); + if (ret < 0) { + DPAA2_PMD_ERR("Update rule(%d) in FS table(%d) failed", + flow->entry_index, flow->tc_id); + return ret; } return 0; } static int -dpaa2_flow_qos_rule_insert_hole(struct dpaa2_dev_priv *priv, +_dpaa2_flow_rule_insert_hole(struct dpaa2_generic_flow *flow, int offset, int size) { - struct dpaa2_dev_flow *curr; - int ret; - - curr = priv->curr; - if (!curr) { - DPAA2_PMD_ERR("Current qos flow insert hole failed."); - return -EINVAL; + if (offset < flow->rule_size) { + memmove(flow->key_addr + offset + size, + flow->key_addr + offset, + flow->rule_size - offset); + memset(flow->key_addr + offset, 0, size); + + memmove(flow->mask_addr + offset + size, + flow->mask_addr + offset, + flow->rule_size - offset); + memset(flow->mask_addr + offset, 0, size); + flow->rule_size += size; } else { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - } - - curr = LIST_FIRST(&priv->flows); - while (curr) { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - curr = LIST_NEXT(curr, next); + flow->rule_size = offset + size; } return 0; } static int -dpaa2_flow_fs_rule_insert_hole(struct dpaa2_dev_priv *priv, - int offset, int size, int tc_id) +dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type dist_type, + uint16_t entry_size, uint8_t tc_id) { - struct dpaa2_dev_flow *curr; + struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); + struct dpaa2_generic_flow *qos_flow; + struct dpaa2_generic_flow *fs_flow; int ret; - curr = priv->curr; - if (!curr || curr->tc_id != tc_id) { - DPAA2_PMD_ERR("Current flow insert hole failed."); - return -EINVAL; - } else { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - curr = LIST_FIRST(&priv->flows); - while (curr) { - if (curr->tc_id != tc_id) { - curr = LIST_NEXT(curr, next); - continue; + qos_flow = curr->qos_flow; + fs_flow = curr->fs_flow; + if (qos_flow && dist_type == DPAA2_FLOW_QOS_TYPE) { + qos_flow->rule_cfg.key_size = entry_size; + ret = dpaa2_flow_add_qos_rule(priv, qos_flow); + if (ret) + return ret; + } else if (dist_type == DPAA2_FLOW_FS_TYPE && + fs_flow && fs_flow->tc_id == tc_id) { + fs_flow->rule_cfg.key_size = entry_size; + ret = dpaa2_flow_add_fs_rule(priv, fs_flow); + if (ret) + return ret; } - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; curr = LIST_NEXT(curr, next); } return 0; } +static void +dpaa2_flow_rule_insert_hole(struct dpaa2_dev_priv *priv, + int offset, int size, int tc_id, + enum dpaa2_flow_dist_type dist_type) +{ + struct dpaa2_dev_flow *flow; + struct dpaa2_generic_flow *curr; + + curr = priv->cur_flow; + if (curr) + _dpaa2_flow_rule_insert_hole(curr, offset, size); + + flow = LIST_FIRST(&priv->flows); + while (flow) { + if (dist_type == DPAA2_FLOW_QOS_TYPE) + curr = flow->qos_flow; + else + curr = flow->fs_flow; + flow = LIST_NEXT(flow, next); + if (!curr) + continue; + if (dist_type == DPAA2_FLOW_FS_TYPE && + curr->tc_id != tc_id) + continue; + if (curr->ip_src || curr->ip_dst) + _dpaa2_flow_rule_insert_hole(curr, offset, size); + } +} + static int dpaa2_flow_faf_advance(struct dpaa2_dev_priv *priv, int faf_byte, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int offset, ret; struct dpaa2_key_profile *key_profile; - int num, pos; + uint8_t idx, offset = 0xff; + struct key_prot_field prot = {0}; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; + key_profile = &priv->flow_profile.qos_profile.key_profile; else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; + key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile; - num = key_profile->num; - - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off++; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, 1); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, 1, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - - key_profile->key_size[pos] = 1; - key_profile->prot_field[pos].type = DPAA2_FAF_KEY; - key_profile->prot_field[pos].key_field = faf_byte; - key_profile->num++; - - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; + prot.type = DPAA2_FAF_KEY; + prot.key_field = faf_byte; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + 1, &offset, insert_offset, &prot); + dpaa2_flow_rule_insert_hole(priv, offset, 1, tc_id, dist_type); - key_profile->key_max_size++; - - return pos; + return idx; } static int @@ -762,60 +994,27 @@ dpaa2_flow_pr_advance(struct dpaa2_dev_priv *priv, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int offset, ret; struct dpaa2_key_profile *key_profile; - int num, pos; + uint8_t idx, offset = 0xff; + struct key_prot_field prot = {0}; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; + key_profile = &priv->flow_profile.qos_profile.key_profile; else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - - num = key_profile->num; + key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile; - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off += pr_size; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, pr_size); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, pr_size, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - - key_profile->key_size[pos] = pr_size; - key_profile->prot_field[pos].type = DPAA2_PR_KEY; - key_profile->prot_field[pos].key_field = - (pr_offset << 16) | pr_size; - key_profile->num++; + prot.type = DPAA2_PR_KEY; + prot.key_field = (pr_offset << 16) | pr_size; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + pr_size, &offset, insert_offset, &prot); + dpaa2_flow_rule_insert_hole(priv, offset, pr_size, tc_id, dist_type); - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; - - key_profile->key_max_size += pr_size; - - return pos; + return idx; } /* Move IPv4/IPv6 addresses to fill new extract previous IP address. @@ -830,9 +1029,9 @@ dpaa2_flow_key_profile_advance(enum net_prot prot, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int offset, ret; struct dpaa2_key_profile *key_profile; - int num, pos; + uint8_t idx, offset = 0xff; + struct key_prot_field prot_field; if (dpaa2_flow_ip_address_extract(prot, field)) { DPAA2_PMD_ERR("%s only for none IP address extract", @@ -841,66 +1040,35 @@ dpaa2_flow_key_profile_advance(enum net_prot prot, } if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; + key_profile = &priv->flow_profile.qos_profile.key_profile; else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - - num = key_profile->num; + key_profile = &priv->flow_profile.tc_profile[tc_id].key_profile; - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off += field_size; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, field_size); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, field_size, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - - key_profile->key_size[pos] = field_size; - key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY; - key_profile->prot_field[pos].prot = prot; - key_profile->prot_field[pos].key_field = field; - key_profile->num++; - - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; + prot_field.type = DPAA2_NET_PROT_KEY; + prot_field.prot = prot; + prot_field.key_field = field; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + field_size, &offset, insert_offset, &prot_field); + dpaa2_flow_rule_insert_hole(priv, offset, field_size, tc_id, dist_type); if (dpaa2_flow_l4_src_port_extract(prot, field)) { - key_profile->l4_src_port_present = 1; - key_profile->l4_src_port_pos = pos; - key_profile->l4_src_port_offset = - key_profile->key_offset[pos]; + key_profile->l4_sp_present = 1; + key_profile->l4_sp_extract_idx = idx; + key_profile->l4_sp_key_offset = + key_profile->key_offset[idx]; } else if (dpaa2_flow_l4_dst_port_extract(prot, field)) { - key_profile->l4_dst_port_present = 1; - key_profile->l4_dst_port_pos = pos; - key_profile->l4_dst_port_offset = - key_profile->key_offset[pos]; + key_profile->l4_dp_present = 1; + key_profile->l4_dp_extract_idx = idx; + key_profile->l4_dp_key_offset = + key_profile->key_offset[idx]; } - key_profile->key_max_size += field_size; - return pos; + return idx; } static int @@ -909,44 +1077,34 @@ dpaa2_flow_faf_add_hdr(int faf_byte, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int pos, i, offset; - struct dpaa2_key_extract *key_extract; + int extract_idx; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; + struct dpkg_extract extract; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + dpkg = &tbl_profile->dpkg; if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - pos = dpaa2_flow_faf_advance(priv, + extract_idx = dpaa2_flow_faf_advance(priv, faf_byte, dist_type, tc_id, insert_offset); - if (pos < 0) - return pos; + if (extract_idx < 0) + return extract_idx; - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } - } - - offset = DPAA2_FAFE_PSR_OFFSET + faf_byte; - - extracts[pos].type = DPKG_EXTRACT_FROM_PARSE; - extracts[pos].extract.from_parse.offset = offset; - extracts[pos].extract.from_parse.size = 1; - - dpkg->num_extracts++; + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_PARSE; + extract.extract.from_parse.offset = faf_byte; + extract.extract.from_parse.size = 1; + dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract); return 0; } @@ -957,48 +1115,40 @@ dpaa2_flow_pr_add_hdr(uint32_t pr_offset, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int pos, i; - struct dpaa2_key_extract *key_extract; + int extract_idx; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; + struct dpkg_extract extract; - if ((pr_offset + pr_size) > DPAA2_FAPR_SIZE) { + if ((pr_offset + pr_size) > DPAA2_PSR_RESULT_SIZE) { DPAA2_PMD_ERR("PR extracts(%d:%d) overflow", pr_offset, pr_size); return -EINVAL; } if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + dpkg = &tbl_profile->dpkg; if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - pos = dpaa2_flow_pr_advance(priv, + extract_idx = dpaa2_flow_pr_advance(priv, pr_offset, pr_size, dist_type, tc_id, insert_offset); - if (pos < 0) - return pos; - - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } - } + if (extract_idx < 0) + return extract_idx; - extracts[pos].type = DPKG_EXTRACT_FROM_PARSE; - extracts[pos].extract.from_parse.offset = pr_offset; - extracts[pos].extract.from_parse.size = pr_size; - - dpkg->num_extracts++; + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_PARSE; + extract.extract.from_parse.offset = pr_offset; + extract.extract.from_parse.size = pr_size; + dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract); return 0; } @@ -1010,18 +1160,17 @@ dpaa2_flow_extract_add_hdr(enum net_prot prot, enum dpaa2_flow_dist_type dist_type, int tc_id, int *insert_offset) { - int pos, i; - struct dpaa2_key_extract *key_extract; + int extract_idx; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; + struct dpkg_extract extract; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + dpkg = &tbl_profile->dpkg; if (dpaa2_flow_ip_address_extract(prot, field)) { DPAA2_PMD_ERR("%s only for none IP address extract", @@ -1034,52 +1183,86 @@ dpaa2_flow_extract_add_hdr(enum net_prot prot, return -EINVAL; } - pos = dpaa2_flow_key_profile_advance(prot, + extract_idx = dpaa2_flow_key_profile_advance(prot, field, field_size, priv, dist_type, tc_id, insert_offset); - if (pos < 0) - return pos; + if (extract_idx < 0) + return extract_idx; - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_HDR; + extract.extract.from_hdr.prot = prot; + extract.extract.from_hdr.type = DPKG_FULL_FIELD; + extract.extract.from_hdr.field = field; + dpaa2_dpkg_insert_extract(dpkg, extract_idx, &extract); + + return 0; +} + +static inline int +dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile, + enum key_prot_type type, enum net_prot prot, uint32_t key_field) +{ + int extract_idx; + struct key_prot_field *prot_field; + + if (dpaa2_flow_ip_address_extract(prot, key_field)) { + DPAA2_PMD_ERR("%s only for none IP address extract", + __func__); + return -EINVAL; } - extracts[pos].type = DPKG_EXTRACT_FROM_HDR; - extracts[pos].extract.from_hdr.prot = prot; - extracts[pos].extract.from_hdr.type = DPKG_FULL_FIELD; - extracts[pos].extract.from_hdr.field = field; + prot_field = key_profile->prot_field; + for (extract_idx = 0; extract_idx < key_profile->num; extract_idx++) { + if (type == DPAA2_NET_PROT_KEY && + prot_field[extract_idx].prot == prot && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + else if (type == DPAA2_FAF_KEY && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + else if (type == DPAA2_PR_KEY && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + } - dpkg->num_extracts++; + if (type == DPAA2_NET_PROT_KEY && + dpaa2_flow_l4_src_port_extract(prot, key_field)) { + if (key_profile->l4_sp_present) + return key_profile->l4_sp_extract_idx; + } else if (type == DPAA2_NET_PROT_KEY && + dpaa2_flow_l4_dst_port_extract(prot, key_field)) { + if (key_profile->l4_dp_present) + return key_profile->l4_dp_extract_idx; + } - return 0; + return -ENXIO; } static int -dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, +_dpaa2_flow_extract_add_raw(struct dpaa2_dev_priv *priv, int offset, int size, enum dpaa2_flow_dist_type dist_type, int tc_id) { - struct dpaa2_key_extract *key_extract; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpkg_profile_cfg *dpkg; struct dpaa2_key_profile *key_profile; - int last_extract_size, index, pos, item_size; + int last_extract_size, index, raw_idx, item_size; uint8_t num_extracts; uint32_t field; + int ret; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; - - dpkg = &key_extract->dpkg; - key_profile = &key_extract->key_profile; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - key_profile->raw_region.raw_start = 0; - key_profile->raw_region.raw_size = 0; + dpkg = &tbl_profile->dpkg; + key_profile = &tbl_profile->key_profile; last_extract_size = (size % DPAA2_FLOW_MAX_KEY_SIZE); num_extracts = (size / DPAA2_FLOW_MAX_KEY_SIZE); @@ -1088,6 +1271,13 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, else last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE; + if ((key_profile->num + num_extracts) > + DPKG_MAX_NUM_OF_EXTRACTS) { + DPAA2_PMD_ERR("%s Failed to expand raw extracts", + __func__); + return -EINVAL; + } + for (index = 0; index < num_extracts; index++) { if (index == num_extracts - 1) item_size = last_extract_size; @@ -1096,25 +1286,22 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; field |= item_size; - pos = dpaa2_flow_key_profile_advance(NET_PROT_PAYLOAD, + ret = dpaa2_flow_extract_search(key_profile, + DPAA2_NET_PROT_KEY, NET_PROT_PAYLOAD, field); + if (ret >= 0) { + offset += item_size; + continue; + } + + raw_idx = dpaa2_flow_key_profile_advance(NET_PROT_PAYLOAD, field, item_size, priv, dist_type, tc_id, NULL); - if (pos < 0) - return pos; - - dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA; - dpkg->extracts[pos].extract.from_data.size = item_size; - dpkg->extracts[pos].extract.from_data.offset = offset; - - if (index == 0) { - key_profile->raw_extract_pos = pos; - key_profile->raw_extract_off = - key_profile->key_offset[pos]; - key_profile->raw_region.raw_start = offset; - } - key_profile->raw_extract_num++; - key_profile->raw_region.raw_size += - key_profile->key_size[pos]; + if (raw_idx < 0) + return raw_idx; + + dpkg->extracts[raw_idx].type = DPKG_EXTRACT_FROM_DATA; + dpkg->extracts[raw_idx].extract.from_data.size = item_size; + dpkg->extracts[raw_idx].extract.from_data.offset = offset; offset += item_size; dpkg->num_extracts++; @@ -1128,247 +1315,16 @@ dpaa2_flow_extract_add_raw(struct dpaa2_dev_priv *priv, int offset, int size, enum dpaa2_flow_dist_type dist_type, int tc_id, int *recfg) { - struct dpaa2_key_profile *key_profile; - struct dpaa2_raw_region *raw_region; - int end = offset + size, ret = 0, extract_extended, sz_extend; - int start_cmp, end_cmp, new_size, index, pos, end_pos; - int last_extract_size, item_size, num_extracts, bk_num = 0; - struct dpkg_extract extract_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - uint8_t key_offset_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - uint8_t key_size_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - struct key_prot_field prot_field_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - struct dpaa2_raw_region raw_hole; - struct dpkg_profile_cfg *dpkg; - enum net_prot prot; - uint32_t field; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - key_profile = &priv->extract.qos_key_extract.key_profile; - dpkg = &priv->extract.qos_key_extract.dpkg; - } else { - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - dpkg = &priv->extract.tc_key_extract[tc_id].dpkg; - } + int ret; - raw_region = &key_profile->raw_region; - if (!raw_region->raw_size) { - /* New RAW region*/ - ret = dpaa2_flow_extract_new_raw(priv, offset, size, + ret = _dpaa2_flow_extract_add_raw(priv, offset, size, dist_type, tc_id); - if (!ret && recfg) - (*recfg) |= dist_type; - - return ret; - } - start_cmp = raw_region->raw_start; - end_cmp = raw_region->raw_start + raw_region->raw_size; - - if (offset >= start_cmp && end <= end_cmp) - return 0; - - sz_extend = 0; - new_size = raw_region->raw_size; - if (offset < start_cmp) { - sz_extend += start_cmp - offset; - new_size += (start_cmp - offset); - } - if (end > end_cmp) { - sz_extend += end - end_cmp; - new_size += (end - end_cmp); - } - - last_extract_size = (new_size % DPAA2_FLOW_MAX_KEY_SIZE); - num_extracts = (new_size / DPAA2_FLOW_MAX_KEY_SIZE); - if (last_extract_size) - num_extracts++; - else - last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE; - - if ((key_profile->num + num_extracts - - key_profile->raw_extract_num) >= - DPKG_MAX_NUM_OF_EXTRACTS) { - DPAA2_PMD_ERR("%s Failed to expand raw extracts", - __func__); - return -EINVAL; - } - - if (offset < start_cmp) { - raw_hole.raw_start = key_profile->raw_extract_off; - raw_hole.raw_size = start_cmp - offset; - raw_region->raw_start = offset; - raw_region->raw_size += start_cmp - offset; - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size); - if (ret) - return ret; - } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size, tc_id); - if (ret) - return ret; - } - } - - if (end > end_cmp) { - raw_hole.raw_start = - key_profile->raw_extract_off + - raw_region->raw_size; - raw_hole.raw_size = end - end_cmp; - raw_region->raw_size += end - end_cmp; - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size); - if (ret) - return ret; - } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size, tc_id); - if (ret) - return ret; - } - } - - end_pos = key_profile->raw_extract_pos + - key_profile->raw_extract_num; - if (key_profile->num > end_pos) { - bk_num = key_profile->num - end_pos; - memcpy(extract_bk, &dpkg->extracts[end_pos], - bk_num * sizeof(struct dpkg_extract)); - memcpy(key_offset_bk, &key_profile->key_offset[end_pos], - bk_num * sizeof(uint8_t)); - memcpy(key_size_bk, &key_profile->key_size[end_pos], - bk_num * sizeof(uint8_t)); - memcpy(prot_field_bk, &key_profile->prot_field[end_pos], - bk_num * sizeof(struct key_prot_field)); - - for (index = 0; index < bk_num; index++) { - key_offset_bk[index] += sz_extend; - prot = prot_field_bk[index].prot; - field = prot_field_bk[index].key_field; - if (dpaa2_flow_l4_src_port_extract(prot, - field)) { - key_profile->l4_src_port_present = 1; - key_profile->l4_src_port_pos = end_pos + index; - key_profile->l4_src_port_offset = - key_offset_bk[index]; - } else if (dpaa2_flow_l4_dst_port_extract(prot, - field)) { - key_profile->l4_dst_port_present = 1; - key_profile->l4_dst_port_pos = end_pos + index; - key_profile->l4_dst_port_offset = - key_offset_bk[index]; - } - } - } - - pos = key_profile->raw_extract_pos; - - for (index = 0; index < num_extracts; index++) { - if (index == num_extracts - 1) - item_size = last_extract_size; - else - item_size = DPAA2_FLOW_MAX_KEY_SIZE; - field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; - field |= item_size; - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - key_profile->key_size[pos] = item_size; - key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY; - key_profile->prot_field[pos].prot = NET_PROT_PAYLOAD; - key_profile->prot_field[pos].key_field = field; - - dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA; - dpkg->extracts[pos].extract.from_data.size = item_size; - dpkg->extracts[pos].extract.from_data.offset = offset; - offset += item_size; - pos++; - } - - if (bk_num) { - memcpy(&dpkg->extracts[pos], extract_bk, - bk_num * sizeof(struct dpkg_extract)); - memcpy(&key_profile->key_offset[end_pos], - key_offset_bk, bk_num * sizeof(uint8_t)); - memcpy(&key_profile->key_size[end_pos], - key_size_bk, bk_num * sizeof(uint8_t)); - memcpy(&key_profile->prot_field[end_pos], - prot_field_bk, bk_num * sizeof(struct key_prot_field)); - } - - extract_extended = num_extracts - key_profile->raw_extract_num; - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - key_profile->ip_addr_extract_pos += extract_extended; - key_profile->ip_addr_extract_off += sz_extend; - } - key_profile->raw_extract_num = num_extracts; - key_profile->num += extract_extended; - key_profile->key_max_size += sz_extend; - - dpkg->num_extracts += extract_extended; if (!ret && recfg) - (*recfg) |= dist_type; + (*recfg) |= true; return ret; } -static inline int -dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile, - enum key_prot_type type, enum net_prot prot, uint32_t key_field) -{ - int pos; - struct key_prot_field *prot_field; - - if (dpaa2_flow_ip_address_extract(prot, key_field)) { - DPAA2_PMD_ERR("%s only for none IP address extract", - __func__); - return -EINVAL; - } - - prot_field = key_profile->prot_field; - for (pos = 0; pos < key_profile->num; pos++) { - if (type == DPAA2_NET_PROT_KEY && - prot_field[pos].prot == prot && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - else if (type == DPAA2_FAF_KEY && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - else if (type == DPAA2_PR_KEY && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - } - - if (type == DPAA2_NET_PROT_KEY && - dpaa2_flow_l4_src_port_extract(prot, key_field)) { - if (key_profile->l4_src_port_present) - return key_profile->l4_src_port_pos; - } else if (type == DPAA2_NET_PROT_KEY && - dpaa2_flow_l4_dst_port_extract(prot, key_field)) { - if (key_profile->l4_dst_port_present) - return key_profile->l4_dst_port_pos; - } - - return -ENXIO; -} - static inline int dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile, enum key_prot_type type, enum net_prot prot, uint32_t key_field) @@ -1384,71 +1340,45 @@ dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile, static int dpaa2_flow_faf_add_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, - enum dpaa2_rx_faf_offset faf_bit_off, - int group, - enum dpaa2_flow_dist_type dist_type) + struct dpaa2_generic_flow *flow, uint32_t faf_bit_off, + int group, enum dpaa2_flow_dist_type dist_type) { int offset; uint8_t *key_addr; uint8_t *mask_addr; - struct dpaa2_key_extract *key_extract; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; uint8_t faf_byte = faf_bit_off / 8; uint8_t faf_bit_in_byte = faf_bit_off % 8; faf_bit_in_byte = 7 - faf_bit_in_byte; - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - key_extract = &priv->extract.qos_key_extract; - key_profile = &key_extract->key_profile; - - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (offset < 0) { - DPAA2_PMD_ERR("%s QoS key extract failed", __func__); - return -EINVAL; - } - key_addr = flow->qos_key_addr + offset; - mask_addr = flow->qos_mask_addr + offset; - - if (!(*key_addr) && - key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT && - offset >= flow->qos_rule_size) - flow->qos_rule_size = offset + sizeof(uint8_t); - - *key_addr |= (1 << faf_bit_in_byte); - *mask_addr |= (1 << faf_bit_in_byte); + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[group]; + key_profile = &tbl_profile->key_profile; + offset = dpaa2_flow_extract_key_offset(key_profile, + DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); + if (offset < 0) { + DPAA2_PMD_ERR("%s QoS key extract failed", __func__); + return -EINVAL; } + key_addr = flow->key_addr + offset; + mask_addr = flow->mask_addr + offset; - if (dist_type & DPAA2_FLOW_FS_TYPE) { - key_extract = &priv->extract.tc_key_extract[group]; - key_profile = &key_extract->key_profile; + if (!(*key_addr) && + !(flow->ip_src || flow->ip_dst) && + offset >= flow->rule_size) + flow->rule_size = offset + sizeof(uint8_t); - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (offset < 0) { - DPAA2_PMD_ERR("%s TC[%d] key extract failed", - __func__, group); - return -EINVAL; - } - key_addr = flow->fs_key_addr + offset; - mask_addr = flow->fs_mask_addr + offset; - - if (!(*key_addr) && - key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT && - offset >= flow->fs_rule_size) - flow->fs_rule_size = offset + sizeof(uint8_t); - - *key_addr |= (1 << faf_bit_in_byte); - *mask_addr |= (1 << faf_bit_in_byte); - } + *key_addr |= (1 << faf_bit_in_byte); + *mask_addr |= (1 << faf_bit_in_byte); return 0; } static inline int -dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow, +dpaa2_flow_pr_rule_data_set(struct dpaa2_generic_flow *flow, struct dpaa2_key_profile *key_profile, uint32_t pr_offset, uint32_t pr_size, const void *key, const void *mask, @@ -1465,42 +1395,23 @@ dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow, pr_offset, pr_size); return -EINVAL; } - sprintf(offset_info, "offset(%d)", offset); - sprintf(size_info, "size(%d)", pr_size); - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, pr_size); - memcpy((flow->qos_mask_addr + offset), mask, pr_size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + pr_size; - } else if ((offset + pr_size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", - offset_info, rule_size_info, - offset_info, size_info, - rule_size_info); - return -EINVAL; - } - } - } - - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, pr_size); - memcpy((flow->fs_mask_addr + offset), mask, pr_size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + pr_size; - } else if ((offset + pr_size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", - offset_info, rule_size_info, - offset_info, size_info, - rule_size_info); - return -EINVAL; - } + snprintf(offset_info, sizeof(offset_info), "offset(%d)", offset); + snprintf(size_info, sizeof(size_info), "size(%d)", pr_size); + + snprintf(rule_size_info, sizeof(rule_size_info), "%s rule size(%d)", + dist_type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", flow->rule_size); + memcpy((flow->key_addr + offset), key, pr_size); + memcpy((flow->mask_addr + offset), mask, pr_size); + if (!(flow->ip_src || flow->ip_dst)) { + if (offset >= flow->rule_size) { + flow->rule_size = offset + pr_size; + } else if ((offset + pr_size) > flow->rule_size) { + DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", + offset_info, rule_size_info, + offset_info, size_info, + rule_size_info); + return -EINVAL; } } @@ -1508,13 +1419,13 @@ dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow, } static inline int -dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow, +dpaa2_flow_hdr_rule_data_set(struct dpaa2_generic_flow *flow, struct dpaa2_key_profile *key_profile, enum net_prot prot, uint32_t field, int size, const void *key, const void *mask, enum dpaa2_flow_dist_type dist_type) { - int offset; + int offset, i; char offset_info[64], size_info[64], rule_size_info[64]; if (dpaa2_flow_ip_address_extract(prot, field)) { @@ -1530,40 +1441,25 @@ dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow, prot, field); return -EINVAL; } - sprintf(offset_info, "offset(%d)", offset); - sprintf(size_info, "size(%d)", size); - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, size); - memcpy((flow->qos_mask_addr + offset), mask, size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + size; - } else if ((offset + size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } - } - } + snprintf(offset_info, sizeof(offset_info), "offset(%d)", offset); + snprintf(size_info, sizeof(size_info), "size(%d)", size); - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, size); - memcpy((flow->fs_mask_addr + offset), mask, size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + size; - } else if ((offset + size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } + snprintf(rule_size_info, sizeof(rule_size_info), "%s rule size(%d)", + dist_type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", + flow->rule_size); + + for (i = 0; i < size; i++) { + *(flow->key_addr + offset + i) |= *((const uint8_t *)key + i); + *(flow->mask_addr + offset + i) |= *((const uint8_t *)mask + i); + } + if (!(flow->ip_src || flow->ip_dst)) { + if (offset >= flow->rule_size) { + flow->rule_size = offset + size; + } else if ((offset + size) > flow->rule_size) { + DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", + __func__, offset_info, rule_size_info, + offset_info, size_info, rule_size_info); + return -EINVAL; } } @@ -1571,7 +1467,7 @@ dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow, } static inline int -dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow, +dpaa2_flow_raw_rule_data_set(struct dpaa2_generic_flow *flow, struct dpaa2_key_profile *key_profile, uint32_t extract_offset, int size, const void *key, const void *mask, @@ -1591,37 +1487,22 @@ dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow, extract_offset, size); return -EINVAL; } - sprintf(offset_info, "offset(%d)", offset); - sprintf(size_info, "size(%d)", size); - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, size); - memcpy((flow->qos_mask_addr + offset), mask, size); - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + size; - } else if ((offset + size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } - } - - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, size); - memcpy((flow->fs_mask_addr + offset), mask, size); - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + size; - } else if ((offset + size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } + snprintf(offset_info, sizeof(offset_info), "offset(%d)", offset); + snprintf(size_info, sizeof(size_info), "size(%d)", size); + + snprintf(rule_size_info, sizeof(rule_size_info), "%s rule size(%d)", + dist_type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", flow->rule_size); + + memcpy((flow->key_addr + offset), key, size); + memcpy((flow->mask_addr + offset), mask, size); + if (offset >= flow->rule_size) { + flow->rule_size = offset + size; + } else if ((offset + size) > flow->rule_size) { + DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", + __func__, offset_info, rule_size_info, + offset_info, size_info, rule_size_info); + return -EINVAL; } return 0; @@ -1692,14 +1573,6 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; - case RTE_FLOW_ITEM_TYPE_MPLS: - mask_support = (const char *)&dpaa2_flow_item_mpls_mask; - size = sizeof(struct rte_flow_item_mpls); - break; - case RTE_FLOW_ITEM_TYPE_PPPOES: - mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; - size = sizeof(struct rte_flow_item_pppoe); - break; default: return -EINVAL; } @@ -1717,19 +1590,17 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, static int dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, - enum dpaa2_rx_faf_offset faf_off, - enum dpaa2_flow_dist_type dist_type, - int group, int *recfg) + struct dpaa2_generic_flow *flow, uint32_t faf_bit_off, + enum dpaa2_flow_dist_type dist_type, int group, int *recfg) { - int ret, index, local_cfg = 0; - struct dpaa2_key_extract *extract; + int ret, index, local_cfg = false; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; - uint8_t faf_byte = faf_off / 8; + uint8_t faf_byte = faf_bit_off / 8; - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - extract = &priv->extract.qos_key_extract; - key_profile = &extract->key_profile; + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); @@ -1742,20 +1613,18 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, return -EINVAL; } - local_cfg |= DPAA2_FLOW_QOS_TYPE; + local_cfg = true; } - ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group, + ret = dpaa2_flow_faf_add_rule(priv, flow, faf_bit_off, group, DPAA2_FLOW_QOS_TYPE); if (ret) { DPAA2_PMD_ERR("QoS faf rule set failed"); - return -EINVAL; + return ret; } - } - - if (dist_type & DPAA2_FLOW_FS_TYPE) { - extract = &priv->extract.tc_key_extract[group]; - key_profile = &extract->key_profile; + } else if (dist_type == DPAA2_FLOW_FS_TYPE) { + tbl_profile = &priv->flow_profile.tc_profile[group]; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); @@ -1769,10 +1638,10 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, return -EINVAL; } - local_cfg |= DPAA2_FLOW_FS_TYPE; + local_cfg = true; } - ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group, + ret = dpaa2_flow_faf_add_rule(priv, flow, faf_bit_off, group, DPAA2_FLOW_FS_TYPE); if (ret) { DPAA2_PMD_ERR("FS[%d] faf rule set failed", @@ -1782,29 +1651,29 @@ dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, } if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } static int -dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow, +dpaa2_flow_add_pr_extract_rule(struct dpaa2_generic_flow *flow, uint32_t pr_offset, uint32_t pr_size, const void *key, const void *mask, struct dpaa2_dev_priv *priv, int tc_id, int *recfg, enum dpaa2_flow_dist_type dist_type) { - int index, ret, local_cfg = 0; - struct dpaa2_key_extract *key_extract; + int index, ret, local_cfg = false; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; uint32_t pr_field = pr_offset << 16 | pr_size; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - key_profile = &key_extract->key_profile; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_PR_KEY, NET_PROT_NONE, pr_field); @@ -1818,7 +1687,7 @@ dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow, return ret; } - local_cfg |= dist_type; + local_cfg = true; } ret = dpaa2_flow_pr_rule_data_set(flow, key_profile, @@ -1831,31 +1700,31 @@ dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow, } if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } static int -dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow, +dpaa2_flow_add_hdr_extract_rule(struct dpaa2_generic_flow *flow, enum net_prot prot, uint32_t field, const void *key, const void *mask, int size, struct dpaa2_dev_priv *priv, int tc_id, int *recfg, enum dpaa2_flow_dist_type dist_type) { - int index, ret, local_cfg = 0; - struct dpaa2_key_extract *key_extract; + int index, ret, local_cfg = false; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; if (dpaa2_flow_ip_address_extract(prot, field)) return -EINVAL; if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; + tbl_profile = &priv->flow_profile.qos_profile; else - key_extract = &priv->extract.tc_key_extract[tc_id]; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; - key_profile = &key_extract->key_profile; + key_profile = &tbl_profile->key_profile; index = dpaa2_flow_extract_search(key_profile, DPAA2_NET_PROT_KEY, prot, field); @@ -1869,7 +1738,7 @@ dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow, return ret; } - local_cfg |= dist_type; + local_cfg = true; } ret = dpaa2_flow_hdr_rule_data_set(flow, key_profile, @@ -1882,44 +1751,57 @@ dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow, } if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } static int -dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow, +dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_generic_flow *flow, enum net_prot prot, uint32_t field, const void *key, const void *mask, int size, struct dpaa2_dev_priv *priv, int tc_id, int *recfg, enum dpaa2_flow_dist_type dist_type) { - int local_cfg = 0, num, ipaddr_extract_len = 0; - struct dpaa2_key_extract *key_extract; + int local_cfg = false, update = 0, ret, pos = 0; + struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_key_profile *key_profile; struct dpkg_profile_cfg *dpkg; - uint8_t *key_addr, *mask_addr; - union ip_addr_extract_rule *ip_addr_data; - union ip_addr_extract_rule *ip_addr_mask; - enum net_prot orig_prot; - uint32_t orig_field; - - if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6) - return -EINVAL; + uint8_t *key_addr, *mask_addr, num; + uint8_t ip_addr_offset = 0; - if (prot == NET_PROT_IPV4 && field != NH_FLD_IPV4_SRC_IP && - field != NH_FLD_IPV4_DST_IP) { + if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6) { + DPAA2_PMD_ERR("%s: Invalid protocol(%d)", + __func__, prot); return -EINVAL; } - if (prot == NET_PROT_IPV6 && field != NH_FLD_IPV6_SRC_IP && - field != NH_FLD_IPV6_DST_IP) { - return -EINVAL; + if (prot == NET_PROT_IPV4) { + if (field != NH_FLD_IPV4_SRC_IP && + field != NH_FLD_IPV4_DST_IP) { + DPAA2_PMD_ERR("%s: Invalid ipv4 filed(%d)", + __func__, field); + return -EINVAL; + } + if (size != sizeof(rte_be32_t)) { + DPAA2_PMD_ERR("%s: Invalid ipv4 address size(%d)", + __func__, size); + return -EINVAL; + } + } else { + if (field != NH_FLD_IPV6_SRC_IP && + field != NH_FLD_IPV6_DST_IP) { + DPAA2_PMD_ERR("%s: Invalid ipv6 filed(%d)", + __func__, field); + return -EINVAL; + } + if (size != NH_FLD_IPV6_ADDR_SIZE) { + DPAA2_PMD_ERR("%s: Invalid ipv6 address size(%d)", + __func__, size); + return -EINVAL; + } } - orig_prot = prot; - orig_field = field; - if (prot == NET_PROT_IPV4 && field == NH_FLD_IPV4_SRC_IP) { prot = NET_PROT_IP; @@ -1942,182 +1824,126 @@ dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow, return -EINVAL; } - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - key_extract = &priv->extract.qos_key_extract; - key_profile = &key_extract->key_profile; - dpkg = &key_extract->dpkg; - num = key_profile->num; - key_addr = flow->qos_key_addr; - mask_addr = flow->qos_mask_addr; - } else { - key_extract = &priv->extract.tc_key_extract[tc_id]; - key_profile = &key_extract->key_profile; - dpkg = &key_extract->dpkg; - num = key_profile->num; - key_addr = flow->fs_key_addr; - mask_addr = flow->fs_mask_addr; - } + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + + key_profile = &tbl_profile->key_profile; + dpkg = &tbl_profile->dpkg; + num = key_profile->num; + key_addr = flow->key_addr; + mask_addr = flow->mask_addr; if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (field == NH_FLD_IP_SRC) - key_profile->ip_addr_type = IP_SRC_EXTRACT; - else - key_profile->ip_addr_type = IP_DST_EXTRACT; - ipaddr_extract_len = size; - - key_profile->ip_addr_extract_pos = num; - if (num > 0) { - key_profile->ip_addr_extract_off = - key_profile->key_offset[num - 1] + - key_profile->key_size[num - 1]; - } else { - key_profile->ip_addr_extract_off = 0; - } - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; - } else if (key_profile->ip_addr_type == IP_SRC_EXTRACT) { - if (field == NH_FLD_IP_SRC) { - ipaddr_extract_len = size; - goto rule_configure; - } - key_profile->ip_addr_type = IP_SRC_DST_EXTRACT; - ipaddr_extract_len = size * 2; - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; - } else if (key_profile->ip_addr_type == IP_DST_EXTRACT) { - if (field == NH_FLD_IP_DST) { - ipaddr_extract_len = size; - goto rule_configure; - } - key_profile->ip_addr_type = IP_DST_SRC_EXTRACT; - ipaddr_extract_len = size * 2; - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; + pos = dpaa2_extract_prev_ip_addr_pos(key_profile); + if (pos >= 0) { + ip_addr_offset = key_profile->key_offset[pos] + + key_profile->key_size[pos]; } - key_profile->num++; - key_profile->prot_field[num].type = DPAA2_NET_PROT_KEY; - dpkg->extracts[num].extract.from_hdr.prot = prot; - dpkg->extracts[num].extract.from_hdr.field = field; - dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD; - dpkg->num_extracts++; + ret = dpaa2_extract_ip_addr_add(field, + key_profile, size, &update, &pos); + if (ret) { + DPAA2_PMD_ERR("Add IP address extract failed(%d)", ret); + return ret; + } + if (pos > 1) { + DPAA2_PMD_ERR("Invalid IP address extract position(%d)", pos); + return -EINVAL; + } + if (update) { + key_profile->num++; + key_profile->prot_field[num].type = DPAA2_NET_PROT_KEY; + key_profile->prot_field[num].prot = prot; + key_profile->prot_field[num].key_field = field; - if (dist_type == DPAA2_FLOW_QOS_TYPE) - local_cfg = DPAA2_FLOW_QOS_TYPE; - else - local_cfg = DPAA2_FLOW_FS_TYPE; - -rule_configure: - key_addr += key_profile->ip_addr_extract_off; - ip_addr_data = (union ip_addr_extract_rule *)key_addr; - mask_addr += key_profile->ip_addr_extract_off; - ip_addr_mask = (union ip_addr_extract_rule *)mask_addr; - - if (orig_prot == NET_PROT_IPV4 && - orig_field == NH_FLD_IPV4_SRC_IP) { - if (key_profile->ip_addr_type == IP_SRC_EXTRACT || - key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) { - memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_src, - key, size); - memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_src, - mask, size); - } else { - memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_src, - key, size); - memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_src, - mask, size); - } - } else if (orig_prot == NET_PROT_IPV4 && - orig_field == NH_FLD_IPV4_DST_IP) { - if (key_profile->ip_addr_type == IP_DST_EXTRACT || - key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) { - memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_dst, - key, size); - memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_dst, - mask, size); - } else { - memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_dst, - key, size); - memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_dst, - mask, size); - } - } else if (orig_prot == NET_PROT_IPV6 && - orig_field == NH_FLD_IPV6_SRC_IP) { - if (key_profile->ip_addr_type == IP_SRC_EXTRACT || - key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) { - memcpy(ip_addr_data->ipv6_sd_addr.ipv6_src, - key, size); - memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_src, - mask, size); - } else { - memcpy(ip_addr_data->ipv6_ds_addr.ipv6_src, - key, size); - memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_src, - mask, size); - } - } else if (orig_prot == NET_PROT_IPV6 && - orig_field == NH_FLD_IPV6_DST_IP) { - if (key_profile->ip_addr_type == IP_DST_EXTRACT || - key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) { - memcpy(ip_addr_data->ipv6_ds_addr.ipv6_dst, - key, size); - memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_dst, - mask, size); - } else { - memcpy(ip_addr_data->ipv6_sd_addr.ipv6_dst, - key, size); - memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_dst, - mask, size); - } + dpkg->extracts[num].type = DPKG_EXTRACT_FROM_HDR; + dpkg->extracts[num].extract.from_hdr.prot = prot; + dpkg->extracts[num].extract.from_hdr.field = field; + dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD; + dpkg->num_extracts++; + + local_cfg = true; } - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - flow->qos_rule_size = - key_profile->ip_addr_extract_off + ipaddr_extract_len; + key_addr += ip_addr_offset; + mask_addr += ip_addr_offset; + + if (pos == 0) { + rte_memcpy(key_addr, key, size); + rte_memcpy(mask_addr, mask, size); } else { - flow->fs_rule_size = - key_profile->ip_addr_extract_off + ipaddr_extract_len; + rte_memcpy(key_addr + size, key, size); + rte_memcpy(mask_addr + size, mask, size); } + flow->rule_size = ip_addr_offset + size * (pos + 1); + if (recfg) - *recfg |= local_cfg; + (*recfg) |= local_cfg; return 0; } -static int -dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - int *device_configured) +static void dpaa2_flow_hdr_hexdump(char *dump_buf, size_t buf_size, + const uint8_t *hdr, uint32_t size) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_eth *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; + uint32_t i; + size_t offset = 0; - group = attr->group; + if (!buf_size) + return; - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_eth_mask; + dump_buf[0] = '\0'; + /* Each byte renders as 3 characters ("xx "), so advance the write + * offset by the number of characters actually emitted rather than + * by the byte index. + */ + for (i = 0; i < size && offset < buf_size - 1; i++) { + int len = snprintf(&dump_buf[offset], buf_size - offset, + "%02x ", hdr[i]); - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + if (len < 0) + break; + offset += len; + } +} - if (!spec) +static int +dpaa2_flow_tunnel_eth_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_attr *attr, + const struct rte_flow_item *pattern, int *extract_cfg, + enum dpaa2_flow_dist_type dist_type) +{ + int ret, local_cfg = false; + uint32_t group; + const struct rte_flow_item_eth *spec, *mask; + struct dpaa2_dev_priv *priv = flow->priv; + const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; + + if (!pattern->spec) return 0; + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_eth_mask; + ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ETH); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ethernet failed"); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_eth)); + DPAA2_PMD_WARN("Extract ethernet(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2129,40 +1955,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR0_OFFSET, 1, &spec->src.addr_bytes[0], &mask->src.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[1:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR1_OFFSET, - 2, &spec->src.addr_bytes[1], - &mask->src.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[3:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR3_OFFSET, - 1, &spec->src.addr_bytes[3], - &mask->src.addr_bytes[3], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[4:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR4_OFFSET, - 2, &spec->src.addr_bytes[4], - &mask->src.addr_bytes[4], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - /*SRC[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR0_OFFSET, - 1, &spec->src.addr_bytes[0], - &mask->src.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*SRC[1:2]*/ @@ -2170,7 +1963,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR1_OFFSET, 2, &spec->src.addr_bytes[1], &mask->src.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*SRC[3:1]*/ @@ -2178,7 +1971,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR3_OFFSET, 1, &spec->src.addr_bytes[3], &mask->src.addr_bytes[3], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*SRC[4:2]*/ @@ -2186,7 +1979,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_SADDR4_OFFSET, 2, &spec->src.addr_bytes[4], &mask->src.addr_bytes[4], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; } @@ -2198,40 +1991,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR0_OFFSET, 1, &spec->dst.addr_bytes[0], &mask->dst.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[1:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR1_OFFSET, - 1, &spec->dst.addr_bytes[1], - &mask->dst.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[2:3]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR2_OFFSET, - 3, &spec->dst.addr_bytes[2], - &mask->dst.addr_bytes[2], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[5:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR5_OFFSET, - 1, &spec->dst.addr_bytes[5], - &mask->dst.addr_bytes[5], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - /*DST[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR0_OFFSET, - 1, &spec->dst.addr_bytes[0], - &mask->dst.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*DST[1:1]*/ @@ -2239,7 +1999,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR1_OFFSET, 1, &spec->dst.addr_bytes[1], &mask->dst.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*DST[2:3]*/ @@ -2247,7 +2007,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR2_OFFSET, 3, &spec->dst.addr_bytes[2], &mask->dst.addr_bytes[2], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; /*DST[5:1]*/ @@ -2255,7 +2015,7 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, DPAA2_VXLAN_IN_DADDR5_OFFSET, 1, &spec->dst.addr_bytes[5], &mask->dst.addr_bytes[5], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; } @@ -2265,76 +2025,65 @@ dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_pr_extract_rule(flow, DPAA2_VXLAN_IN_TYPE_OFFSET, sizeof(rte_be16_t), &spec->type, &mask->type, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TYPE_OFFSET, - sizeof(rte_be16_t), &spec->type, &mask->type, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_eth_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_eth *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; if (dpaa2_pattern->in_tunnel) { - return dpaa2_configure_flow_tunnel_eth(flow, - dev, attr, pattern, device_configured); + return dpaa2_flow_tunnel_eth_extract_rule_set(flow, + attr, pattern, extract_cfg, + dist_type); } - group = attr->group; - /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_eth_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + pattern->mask : &dpaa2_flow_item_eth_mask; if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ETH_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_MAC_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ETH_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + bit_offset, dist_type, + attr->group, &local_cfg); + if (extract_cfg && !ret) + (*extract_cfg) |= local_cfg; - (*device_configured) |= local_cfg; - return 0; + return ret; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ETH); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ethernet failed"); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_eth)); + DPAA2_PMD_WARN("Extract ethernet(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2344,14 +2093,7 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, NH_FLD_ETH_SA, &spec->src.addr_bytes, &mask->src.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_SA, &spec->src.addr_bytes, - &mask->src.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -2361,14 +2103,7 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, NH_FLD_ETH_DA, &spec->dst.addr_bytes, &mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_DA, &spec->dst.addr_bytes, - &mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -2378,34 +2113,28 @@ dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, NH_FLD_ETH_TYPE, &spec->type, &mask->type, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_TYPE, &spec->type, - &mask->type, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_tunnel_vlan_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - int *device_configured) + const struct rte_flow_item *pattern, int *extract_cfg, + enum dpaa2_flow_dist_type dist_type) { - int ret, local_cfg = 0; - uint32_t group; + int ret, local_cfg = false; + uint32_t group, bit_offset; const struct rte_flow_item_vlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; group = attr->group; @@ -2414,33 +2143,30 @@ dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow, mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_VLAN_FRAM, - DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_VLAN_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_VLAN_FRAM, - DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, + attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_VLAN); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of vlan not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_vlan)); + DPAA2_PMD_WARN("Extract vlan(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2451,74 +2177,64 @@ dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_pr_extract_rule(flow, DPAA2_VXLAN_IN_TCI_OFFSET, sizeof(rte_be16_t), &spec->tci, &mask->tci, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TCI_OFFSET, - sizeof(rte_be16_t), &spec->tci, &mask->tci, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, group, &local_cfg, dist_type); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_vlan_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_vlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; if (dpaa2_pattern->in_tunnel) { - return dpaa2_configure_flow_tunnel_vlan(flow, - dev, attr, pattern, device_configured); + return dpaa2_flow_tunnel_vlan_extract_rule_set(flow, + attr, pattern, extract_cfg, + dist_type); } - group = attr->group; - /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_VLAN_ID); + if (ret) + return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - if (ret) - return ret; + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; - (*device_configured) |= local_cfg; + if (!spec) { + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_VLAN); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of vlan not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_vlan)); + DPAA2_PMD_WARN("Extract vlan(%s) failed(%d)", + hex_dump, ret); + return ret; } @@ -2528,45 +2244,34 @@ dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN, NH_FLD_VLAN_TCI, &spec->tci, &mask->tci, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN, - NH_FLD_VLAN_TCI, &spec->tci, - &mask->tci, sizeof(rte_be16_t), - priv, group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ipv4_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ipv4 *spec_ipv4 = 0, *mask_ipv4 = 0; const void *key, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; int size; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec_ipv4 = pattern->spec; mask_ipv4 = pattern->mask ? - pattern->mask : &dpaa2_flow_item_ipv4_mask; + pattern->mask : &dpaa2_flow_item_ipv4_mask; if (dpaa2_pattern->in_tunnel) { if (spec_ipv4) { @@ -2574,44 +2279,48 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV4_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_IPV4_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV4_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, + attr->group, &local_cfg); + if (ret) + return ret; } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPV4_ID); if (ret) return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, + attr->group, &local_cfg); if (ret) return ret; if (!spec_ipv4) { - (*device_configured) |= local_cfg; + if (flow->ip_key == NET_PROT_IPV6) { + DPAA2_PMD_ERR("IPv6 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV4; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv4, RTE_FLOW_ITEM_TYPE_IPV4); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of IPv4 not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask_ipv4, + sizeof(struct rte_flow_item_ipv4)); + DPAA2_PMD_WARN("Extract IPv4(%s) failed(%d)", + hex_dump, ret); + return ret; } @@ -2621,20 +2330,11 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, size = sizeof(rte_be32_t); ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IPV4_SRC_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; + flow->ip_src = NET_PROT_IPV4; } if (mask_ipv4->hdr.dst_addr) { @@ -2643,19 +2343,41 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, size = sizeof(rte_be32_t); ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); + NH_FLD_IPV4_DST_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + flow->ip_dst = NET_PROT_IPV4; + } + + if (mask_ipv4->hdr.packet_id) { + key = &spec_ipv4->hdr.packet_id; + mask = &mask_ipv4->hdr.packet_id; + size = sizeof(rte_be16_t); + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, + NH_FLD_IP_ID, key, mask, size, + priv, attr->group, &local_cfg, dist_type); + if (ret) + return ret; + } + + if (mask_ipv4->hdr.fragment_offset) { + key = &spec_ipv4->hdr.fragment_offset; + mask = &mask_ipv4->hdr.fragment_offset; + size = sizeof(rte_be16_t); + + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IP_FRAG_ID); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; + + if (spec_ipv4->hdr.fragment_offset) + DPAA2_PMD_WARN("Unsupport Extract of frag offset"); } if (mask_ipv4->hdr.next_proto_id) { @@ -2664,139 +2386,117 @@ dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, size = sizeof(uint8_t); ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IP_PROTO, key, mask, size, priv, attr->group, + &local_cfg, dist_type); if (ret) return ret; } + if (flow->ip_key == NET_PROT_IPV6) { + DPAA2_PMD_ERR("IPv6 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV4; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ipv6_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ipv6 *spec_ipv6 = 0, *mask_ipv6 = 0; const void *key, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0}; int size; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec_ipv6 = pattern->spec; mask_ipv6 = pattern->mask ? pattern->mask : &dpaa2_flow_item_ipv6_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { if (spec_ipv6) { DPAA2_PMD_ERR("Tunnel-IPv6 distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV6_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_IPV6_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV6_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, + attr->group, &local_cfg); + if (ret) + return ret; } - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPV6_ID); if (ret) return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec_ipv6) { - (*device_configured) |= local_cfg; + if (flow->ip_key == NET_PROT_IPV4) { + DPAA2_PMD_ERR("IPv4 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV6; + + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv6, RTE_FLOW_ITEM_TYPE_IPV6); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of IPv6 not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask_ipv6, + sizeof(struct rte_flow_item_ipv6)); + DPAA2_PMD_WARN("Extract IPv6(%s) failed(%d)", + hex_dump, ret); + return ret; } - if (memcmp((const char *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { + if (memcmp((const void *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { key = &spec_ipv6->hdr.src_addr; mask = &mask_ipv6->hdr.src_addr; size = NH_FLD_IPV6_ADDR_SIZE; ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IPV6_SRC_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; + flow->ip_src = NET_PROT_IPV6; } - if (memcmp((const char *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { + if (memcmp((const void *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { key = &spec_ipv6->hdr.dst_addr; mask = &mask_ipv6->hdr.dst_addr; size = NH_FLD_IPV6_ADDR_SIZE; ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IPV6_DST_IP, key, mask, size, priv, + attr->group, &local_cfg, dist_type); if (ret) return ret; + flow->ip_dst = NET_PROT_IPV6; } if (mask_ipv6->hdr.proto) { @@ -2805,78 +2505,68 @@ dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow, size = sizeof(uint8_t); ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_FS_TYPE); + NH_FLD_IP_PROTO, key, mask, size, priv, attr->group, + &local_cfg, dist_type); if (ret) return ret; } + if (flow->ip_key == NET_PROT_IPV4) { + DPAA2_PMD_ERR("IPv4 flow has been configured"); + return -EINVAL; + } + flow->ip_key = NET_PROT_IPV6; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_icmp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_icmp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_icmp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-ICMP distribution not support"); return -ENOTSUP; } if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ICMP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_ICMP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ICMP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ICMP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ICMP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_icmp)); + DPAA2_PMD_WARN("Extract ICMP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2885,14 +2575,7 @@ dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type, &mask->hdr.icmp_type, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type, - &mask->hdr.icmp_type, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -2901,90 +2584,75 @@ dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, NH_FLD_ICMP_CODE, &spec->hdr.icmp_code, &mask->hdr.icmp_code, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_CODE, &spec->hdr.icmp_code, - &mask->hdr.icmp_code, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_udp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_udp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_udp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { if (spec) { DPAA2_PMD_ERR("Tunnel-UDP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_UDP_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_UDP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_UDP_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_UDP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_UDP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_UDP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_UDP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of UDP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_udp)); + DPAA2_PMD_ERR("Extract UDP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -2993,106 +2661,84 @@ dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port, &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - if (mask->hdr.dst_port) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; + } + if (mask->hdr.dst_port) { ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port, &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_tcp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_tcp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_tcp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { if (spec) { DPAA2_PMD_ERR("Tunnel-TCP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_TCP_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TUNNEL_TCP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_TCP_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_TCP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_TCP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_TCP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_TCP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of TCP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_tcp)); + DPAA2_PMD_ERR("Extract TCP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3101,14 +2747,7 @@ dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port, &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3117,76 +2756,64 @@ dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port, &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_esp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_esp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_esp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-ESP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPSEC_ESP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ESP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ESP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_esp)); + DPAA2_PMD_ERR("Extract IPSEC ESP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3195,14 +2822,7 @@ dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi, &mask->hdr.spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi, - &mask->hdr.spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3211,76 +2831,64 @@ dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq, &mask->hdr.seq, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq, - &mask->hdr.seq, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ah_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ah *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_ah_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-AH distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_AH_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_IPSEC_AH_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_AH_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_AH); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of AH not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_ah)); + DPAA2_PMD_ERR("Extract IPSEC AH(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3289,14 +2897,7 @@ dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH, NH_FLD_IPSEC_AH_SPI, &spec->spi, &mask->spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH, - NH_FLD_IPSEC_AH_SPI, &spec->spi, - &mask->spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3306,63 +2907,58 @@ dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow, return -ENOTSUP; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_sctp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_sctp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_sctp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-SCTP distribution not support"); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_SCTP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_SCTP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_SCTP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; if (!spec) { - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_SCTP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of SCTP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_sctp)); + DPAA2_PMD_ERR("Extract SCTP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3371,14 +2967,7 @@ dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port, &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } @@ -3387,80 +2976,63 @@ dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow, ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port, &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_gre_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_gre *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_gre_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-GRE distribution not support"); return -ENOTSUP; } if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GRE_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_GRE_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GRE_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } - if (!priv->sp_protocol) { - DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); - return -ENOTSUP; - } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_GRE); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of GRE not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_gre)); + DPAA2_PMD_ERR("Extract GRE(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3469,81 +3041,65 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE, - NH_FLD_GRE_TYPE, &spec->protocol, - &mask->protocol, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE, - NH_FLD_GRE_TYPE, &spec->protocol, - &mask->protocol, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + NH_FLD_GRE_TYPE, &spec->protocol, &mask->protocol, + sizeof(rte_be16_t), priv, attr->group, &local_cfg, dist_type); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_vxlan_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - if (!priv->sp_protocol) { - DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); - return -ENOTSUP; - } - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vxlan_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); return -ENOTSUP; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_VXLAN_ID); + if (ret) + return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; - (*device_configured) |= local_cfg; - return 0; + if (!spec) + goto quit; + + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); + return -ENOTSUP; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_VXLAN); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_vxlan)); + DPAA2_PMD_ERR("Extract vXLAN(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3563,55 +3119,45 @@ dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { ret = dpaa2_flow_add_pr_extract_rule(flow, DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + sizeof(mask->vni), spec->vni, mask->vni, + priv, attr->group, &local_cfg, dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; +quit: + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_ecpri_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_ecpri *spec, *mask; struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; + int extract_nb, i; uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; + union dpaa2_sp_fafe_parse fafe; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; if (!priv->sp_protocol) { - DPAA2_PMD_ERR("ROCEV2 flow is not supported without SP."); + DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); return -ENOTSUP; } - group = attr->group; - /* Parse pattern list to get the matching parameters */ spec = pattern->spec; if (pattern->mask) { @@ -3624,353 +3170,111 @@ dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, mask = &dpaa2_flow_item_ecpri_mask; } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); return -ENOTSUP; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_ECPRI_ID); + if (ret) + return ret; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, + attr->group, &local_cfg); + if (ret) + return ret; - (*device_configured) |= local_cfg; - return 0; - } + if (!spec) + goto quit; ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_ECPRI); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_ecpri)); + DPAA2_PMD_ERR("Extract eCPRI(%s) failed(%d)", + hex_dump, ret); return ret; } - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } + memset(&fafe, 0, sizeof(union dpaa2_sp_fafe_parse)); + extract_nb = dpaa2_parser_ecpri_extract(spec, mask, + rule_data, mask_data, extract_size, extract_off, + &fafe, DPAA2_ECPRI_MAX_EXTRACT_NB); + if (extract_nb < 0) { + DPAA2_PMD_ERR("Extract eCPRI from spec/mask failed(%d)", + extract_nb); - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; + return extract_nb; } for (i = 0; i < extract_nb; i++) { ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); + extract_off[i], extract_size[i], + &rule_data[i], &mask_data[i], + priv, attr->group, extract_cfg, + dist_type); if (ret) return ret; } - (*device_configured) |= local_cfg; +quit: + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_gtp_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { int ret, local_cfg = 0; - uint32_t group; + uint32_t bit_offset; const struct rte_flow_item_gtp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv = flow->priv; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - if (!priv->sp_protocol) { - DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); - return -ENOTSUP; - } - - group = attr->group; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; /* Parse pattern list to get the matching parameters */ spec = pattern->spec; mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_gtp_mask; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - if (dpaa2_pattern->in_tunnel) { DPAA2_PMD_ERR("Tunnel-GTP distribution not support"); return -ENOTSUP; } if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GTP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_GTP_ID); if (ret) return ret; ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GTP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + bit_offset, dist_type, attr->group, &local_cfg); if (ret) return ret; - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_GTP); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of GTP not support."); + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_gtp)); + DPAA2_PMD_ERR("Extract GTP(%s) failed(%d)", + hex_dump, ret); return ret; } @@ -3979,298 +3283,153 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP, - NH_FLD_GTP_TEID, &spec->teid, - &mask->teid, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + NH_FLD_GTP_TEID, &spec->teid, &mask->teid, + sizeof(rte_be32_t), priv, attr->group, + &local_cfg, dist_type); if (ret) return ret; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP, - NH_FLD_GTP_TEID, &spec->teid, - &mask->teid, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } static int -dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +dpaa2_flow_raw_extract_rule_set(struct dpaa2_generic_flow *flow, const struct rte_flow_attr *attr, const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_mpls *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_mpls_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + struct dpaa2_dev_priv *priv = flow->priv; + int local_cfg = 0, ret; + struct dpaa2_flow_tbl_profile *tbl_profile; + const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + const struct rte_flow_item_raw *spec = pattern->spec; + const struct rte_flow_item_raw *mask = pattern->mask; - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); - return -ENOTSUP; + /* Need both spec and mask */ + if (!spec || !mask) { + DPAA2_PMD_ERR("spec or mask not present."); + return -EINVAL; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + if (spec->relative) { + /* TBD: relative offset support. + * To support relative offset of previous L3 protocol item, + * extracts should be expanded to identify if the frame is: + * vlan or none-vlan. + * + * To support relative offset of previous L4 protocol item, + * extracts should be expanded to identify if the frame is: + * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6. + */ + DPAA2_PMD_ERR("relative not supported."); + return -EINVAL; + } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + if (spec->search) { + DPAA2_PMD_ERR("search not supported."); + return -EINVAL; + } - (*device_configured) |= local_cfg; - return 0; + /* Spec len and mask len should be same */ + if (spec->length != mask->length) { + DPAA2_PMD_ERR("Spec len and mask len mismatch."); + return -EINVAL; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_MPLS); + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[attr->group]; + + ret = dpaa2_flow_extract_add_raw(priv, + spec->offset, spec->length, dist_type, + attr->group, &local_cfg); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + DPAA2_PMD_ERR("QoS Extract RAW add failed(%d).", ret); return ret; } - if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && - !mask->label_tc_s[2]) - return 0; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, - NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, - mask->label_tc_s, sizeof(mask->label_tc_s), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, - NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, - mask->label_tc_s, sizeof(mask->label_tc_s), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_pppoe *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_pppoe_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) + if (dist_type == DPAA2_FLOW_QOS_TYPE || + dist_type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_raw_rule_data_set(flow, + &tbl_profile->key_profile, + spec->offset, spec->length, + spec->pattern, mask->pattern, + dist_type); + if (ret) { + DPAA2_PMD_ERR("QoS RAW rule data set failed(%d)", ret); return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_PPPOES); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); - return ret; + } } - if (!mask->session_id) - return 0; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, - NH_FLD_PPPOE_SID, &spec->session_id, - &mask->session_id, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, - NH_FLD_PPPOE_SID, &spec->session_id, - &mask->session_id, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - - (*device_configured) |= local_cfg; + if (extract_cfg) + (*extract_cfg) |= local_cfg; return 0; } -static int -dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - struct dpaa2_dev_priv *priv = dev->data->dev_private; - int local_cfg = 0, ret; - uint32_t group; - struct dpaa2_key_extract *qos_key_extract; - struct dpaa2_key_extract *tc_key_extract; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - const struct rte_flow_item_raw *spec = pattern->spec; - const struct rte_flow_item_raw *mask = pattern->mask; - - /* Need both spec and mask */ - if (!spec || !mask) { - DPAA2_PMD_ERR("spec or mask not present."); - return -EINVAL; - } - - if (spec->relative) { - /* TBD: relative offset support. - * To support relative offset of previous L3 protocol item, - * extracts should be expanded to identify if the frame is: - * vlan or none-vlan. - * - * To support relative offset of previous L4 protocol item, - * extracts should be expanded to identify if the frame is: - * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6. - */ - DPAA2_PMD_ERR("relative not supported."); - return -EINVAL; - } - - if (spec->search) { - DPAA2_PMD_ERR("search not supported."); - return -EINVAL; - } - - /* Spec len and mask len should be same */ - if (spec->length != mask->length) { - DPAA2_PMD_ERR("Spec len and mask len mismatch."); - return -EINVAL; - } - - /* Get traffic class index and flow id to be configured */ - group = attr->group; - flow->tc_id = group; - flow->tc_index = attr->priority; - - qos_key_extract = &priv->extract.qos_key_extract; - tc_key_extract = &priv->extract.tc_key_extract[group]; - - ret = dpaa2_flow_extract_add_raw(priv, - spec->offset, spec->length, - DPAA2_FLOW_QOS_TYPE, 0, &local_cfg); - if (ret) { - DPAA2_PMD_ERR("QoS Extract RAW add failed."); - return -EINVAL; - } - - ret = dpaa2_flow_extract_add_raw(priv, - spec->offset, spec->length, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); - if (ret) { - DPAA2_PMD_ERR("FS[%d] Extract RAW add failed.", - group); - return -EINVAL; - } - ret = dpaa2_flow_raw_rule_data_set(flow, - &qos_key_extract->key_profile, - spec->offset, spec->length, - spec->pattern, mask->pattern, - DPAA2_FLOW_QOS_TYPE); - if (ret) { - DPAA2_PMD_ERR("QoS RAW rule data set failed"); - return -EINVAL; - } +static inline int +dpaa2_flow_verify_entry(struct dpaa2_dev_priv *priv, + uint16_t tc, uint16_t entry_idx, + enum dpaa2_flow_dist_type dist_type) +{ + struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - ret = dpaa2_flow_raw_rule_data_set(flow, - &tc_key_extract->key_profile, - spec->offset, spec->length, - spec->pattern, mask->pattern, - DPAA2_FLOW_FS_TYPE); - if (ret) { - DPAA2_PMD_ERR("FS RAW rule data set failed"); - return -EINVAL; + while (curr) { + if (dist_type == DPAA2_FLOW_QOS_TYPE && + curr->qos_flow && + curr->qos_flow->entry_index == entry_idx) { + DPAA2_PMD_ERR("Flow QoS.entry[%d] exists", + curr->qos_flow->entry_index); + return -EEXIST; + } + if (dist_type == DPAA2_FLOW_FS_TYPE && + curr->fs_flow && curr->fs_flow->tc_id == tc && + curr->fs_flow->entry_index == entry_idx) { + DPAA2_PMD_ERR("Flow TC[%d].entry[%d] exists", + tc, curr->fs_flow->entry_index); + return -EEXIST; + } + curr = LIST_NEXT(curr, next); } - (*device_configured) |= local_cfg; - return 0; } static inline int -dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv, - const struct rte_flow_attr *attr) +dpaa2_flow_acquire_entry_idx(struct dpaa2_dev_priv *priv, + uint16_t idx, enum dpaa2_flow_dist_type dist_type, + uint8_t group) { - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); + int occupied = -1; + uint16_t max_entries; + struct dpaa2_flow_tbl_profile *tbl_profile; - while (curr) { - if (curr->tc_id == attr->group && - curr->tc_index == attr->priority) { - DPAA2_PMD_ERR("Flow(TC[%d].entry[%d] exists", - attr->group, attr->priority); + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + max_entries = priv->qos_entries; + } else { + tbl_profile = &priv->flow_profile.tc_profile[group]; + max_entries = priv->fs_entries; + } - return -EINVAL; + if (!dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx)) + return idx; + + idx = 0; + while (idx < max_entries) { + if (!dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx)) { + occupied = idx; + break; } - curr = LIST_NEXT(curr, next); + idx++; } - return 0; + return occupied; } static inline struct rte_eth_dev * @@ -4307,7 +3466,7 @@ dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv, } static inline int -dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, +dpaa2_flow_verify_fs_action(struct dpaa2_dev_priv *priv, const struct rte_flow_attr *attr, const struct rte_flow_action actions[]) { @@ -4333,38 +3492,39 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, rxq->tc_index, rxq->flow_id, attr->group); - return -ENOTSUP; + return -EINVAL; } break; case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: if (!dpaa2_flow_redirect_dev(priv, &actions[j])) { DPAA2_PMD_ERR("Invalid port id of action"); - return -ENOTSUP; + return -EINVAL; } break; case RTE_FLOW_ACTION_TYPE_RSS: - rss_conf = (const struct rte_flow_action_rss *) - (actions[j].conf); + rss_conf = actions[j].conf; if (rss_conf->queue_num > priv->dist_queues) { DPAA2_PMD_ERR("RSS number too large"); - return -ENOTSUP; + return -EINVAL; } - for (i = 0; i < (int)rss_conf->queue_num; i++) { - if (rss_conf->queue[i] >= priv->nb_rx_queues) { - DPAA2_PMD_ERR("RSS queue not in range"); - return -ENOTSUP; - } - rxq = priv->rx_vq[rss_conf->queue[i]]; - if (rxq->tc_index != attr->group) { - DPAA2_PMD_ERR("RSS queue not in group"); - return -ENOTSUP; + if (rss_conf->queue) { + for (i = 0; i < (int)rss_conf->queue_num; i++) { + if (rss_conf->queue[i] >= priv->nb_rx_queues) { + DPAA2_PMD_ERR("RSS queue not in range"); + return -EINVAL; + } + rxq = priv->rx_vq[rss_conf->queue[i]]; + if (rxq->tc_index != attr->group) { + DPAA2_PMD_ERR("RSS queue not in group"); + return -EINVAL; + } } } break; case RTE_FLOW_ACTION_TYPE_PF: - /* Skip this action, have to add for vxlan */ + /* Skip this action, have to add for vxlan*/ case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: @@ -4372,7 +3532,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; default: DPAA2_PMD_ERR("Invalid action type"); - return -ENOTSUP; + return -EINVAL; } j++; } @@ -4380,40 +3540,74 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, return 0; } +static struct dpaa2_queue * +dpaa2_flow_queue_action_to_queue(struct dpaa2_dev_priv *priv, + uint8_t tc_id, uint16_t queue_id) +{ + struct dpaa2_queue *dest_q; + + if (queue_id >= MAX_RX_QUEUES || + !priv->rx_vq[queue_id]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", queue_id); + + return NULL; + } + dest_q = priv->rx_vq[queue_id]; + if (tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + queue_id, + dest_q->tc_index, dest_q->flow_id, + tc_id); + + return NULL; + } + + return dest_q; +} + static int -dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, +dpaa2_flow_fs_action_config(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow, const struct rte_flow_action *rte_action) { + struct rte_dpaa2_device *dpaa2_dev; struct rte_eth_dev *dest_dev; struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; uint64_t flc = 0; - - memset(&flow->fs_action_cfg, 0, - sizeof(struct dpni_fs_action_cfg)); - flow->action_type = rte_action->type; - - if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { - dest_queue = rte_action->conf; - if (dest_queue->index >= MAX_RX_QUEUES || - !priv->rx_vq[dest_queue->index]) { - DPAA2_PMD_ERR("Invalid FSQ index(%d)", - dest_queue->index); - + uint16_t num_tokens; + struct dpaa2_dev_flow_fs_action *fs_action; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + fs_action = &flow->flow_action.fs_action; + if (fs_action->action_type != RTE_FLOW_ACTION_TYPE_END) { + if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV && + (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || + fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR)) { + if (rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_ID && + rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR) { + DPAA2_PMD_ERR("Redirect action can't mix with other action(%d)", + rte_action->type); + return -EINVAL; + } + } else { + DPAA2_PMD_ERR("Single action support only with action(%d)", + fs_action->action_type); return -EINVAL; } - dest_q = priv->rx_vq[dest_queue->index]; - if (flow->tc_id != dest_q->tc_index) { - DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", - dest_queue->index, - dest_q->tc_index, dest_q->flow_id, - flow->tc_id); + } + fs_action->action_type = rte_action->type; + if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { + dest_queue = rte_action->conf; + dest_q = dpaa2_flow_queue_action_to_queue(priv, + flow->tc_id, dest_queue->index); + if (!dest_q) return -EINVAL; - } - flow->fs_action_cfg.options = + + fs_action->fs_action_cfg.options = DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; if (dest_q->data_stashing_off) { @@ -4431,10 +3625,10 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; - flow->fs_action_cfg.flc = flc; - flow->fs_action_cfg.flow_id = dest_q->flow_id; - } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || - flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { + fs_action->fs_action_cfg.flc = flc; + fs_action->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || + fs_action->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { dest_dev = dpaa2_flow_redirect_dev(priv, rte_action); if (!dest_dev) { DPAA2_PMD_ERR("Invalid device to redirect"); @@ -4442,15 +3636,34 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } dest_priv = dest_dev->data->dev_private; - dest_q = dest_priv->tx_vq[0]; - flow->fs_action_cfg.options = - DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; - flow->fs_action_cfg.num_tokens = 1; - flow->fs_action_cfg.redir_tokens[0] = - dest_priv->token; - flow->fs_action_cfg.flow_id = dest_q->flow_id; - } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { - flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; + num_tokens = fs_action->fs_action_cfg.num_tokens; + if (num_tokens >= DPNI_FS_REDIR_MAX_NUM) + return -EINVAL; + fs_action->fs_action_cfg.redir_tokens[num_tokens] = dest_priv->token; + strlcpy(fs_action->dst_name[num_tokens], + dest_priv->eth_dev->data->name, + sizeof(fs_action->dst_name[num_tokens])); + fs_action->fs_action_cfg.num_tokens++; + if (fs_action->fs_action_cfg.num_tokens > 1) { + if (!(priv->options & DPNI_OPT_V8_HAS_REPLICATION)) { + DPAA2_PMD_ERR("0x%08x missed in DPNI creating options(0x%08x)", + DPNI_OPT_V8_HAS_REPLICATION, priv->options); + return -ENOTSUP; + } + fs_action->fs_action_cfg.options = + DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX; + } else { + fs_action->fs_action_cfg.options = + DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; + } + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + fs_action->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; + } else if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_RSS) { + /** Do nothing...*/ + } else { + DPAA2_PMD_ERR("Flow action(%d) not supported!", + fs_action->action_type); + return -ENOTSUP; } return 0; @@ -4478,41 +3691,58 @@ dpaa2_flow_clear_fs_table(struct dpaa2_dev_priv *priv, uint8_t tc_id) { struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - int need_clear = 0, ret; + int fs_num = 0, ret, rss_num = 0; struct fsl_mc_io *dpni = priv->hw; while (curr) { - if (curr->tc_id == tc_id) { - need_clear = 1; - break; + if (curr->fs_flow && curr->fs_flow->tc_id == tc_id) { + if (curr->fs_flow->is_rss) + rss_num++; + else + fs_num++; } curr = LIST_NEXT(curr, next); } - if (need_clear) { + if (rss_num > 1) { + DPAA2_PMD_ERR("TC[%d] should have one RSS flow at most!", + tc_id); + return -EINVAL; + } + if (rss_num && fs_num) { + DPAA2_PMD_ERR("TC[%d] has RSS flow and %d FS flow(s)!", + tc_id, fs_num); + return -EINVAL; + } + + if (fs_num) { ret = dpni_clear_fs_entries(dpni, CMD_PRI_LOW, priv->token, tc_id); if (ret) { DPAA2_PMD_ERR("TC[%d] clear failed", tc_id); return ret; } + priv->flow_profile.tc_profile[tc_id].entry_num = 0; + memset(priv->flow_profile.tc_profile[tc_id].entry_map, + 0, priv->fs_entries); } return 0; } + static int -dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, - uint8_t tc_id, uint16_t dist_size, int rss_dist) +dpaa2_flow_fs_rss_table_config(struct dpaa2_dev_priv *priv, + uint8_t tc_id, int rss_dist) { - struct dpaa2_key_extract *tc_extract; + struct dpaa2_flow_tbl_profile *tbl_profile; uint8_t *key_cfg_buf; - uint64_t key_cfg_iova; int ret; - struct dpni_rx_dist_cfg tc_cfg; + struct dpni_rx_dist_cfg *tc_cfg; struct fsl_mc_io *dpni = priv->hw; uint16_t entry_size; uint16_t key_max_size; + struct dpaa2_queue *queue; ret = dpaa2_flow_clear_fs_table(priv, tc_id); if (ret < 0) { @@ -4520,38 +3750,30 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return ret; } - tc_extract = &priv->extract.tc_key_extract[tc_id]; - key_cfg_buf = priv->extract.tc_extract_param[tc_id]; - key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf, - DPAA2_EXTRACT_PARAM_MAX_SIZE); - if (key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, key_cfg_buf); + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + if (!tbl_profile->dpkg.num_extracts) + return 0; - return -ENOBUFS; - } + key_cfg_buf = priv->flow_profile.tc_profile[tc_id].extract_param; - key_max_size = tc_extract->key_profile.key_max_size; + key_max_size = tbl_profile->key_profile.key_max_size; entry_size = dpaa2_flow_entry_size(key_max_size); - dpaa2_flow_fs_extracts_log(priv, tc_id); - ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, + dpaa2_flow_extracts_log(priv, "Configure", tc_id); + ret = dpkg_prepare_key_cfg(&tbl_profile->dpkg, key_cfg_buf); if (ret < 0) { DPAA2_PMD_ERR("TC[%d] prepare key failed", tc_id); return ret; } - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - tc_cfg.dist_size = dist_size; - tc_cfg.key_cfg_iova = key_cfg_iova; + tc_cfg = &tbl_profile->tc_cfg; if (rss_dist) - tc_cfg.enable = true; + tc_cfg->enable = true; else - tc_cfg.enable = false; - tc_cfg.tc = tc_id; + tc_cfg->enable = false; ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, - priv->token, &tc_cfg); + priv->token, tc_cfg); if (ret < 0) { if (rss_dist) { DPAA2_PMD_ERR("RSS TC[%d] set failed", @@ -4564,13 +3786,27 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return ret; } - if (rss_dist) - return 0; + if (rss_dist) { + tbl_profile->is_rss = true; + goto successful_config; + } + + tbl_profile->is_rss = false; - tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = priv->default_flow; - ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, - priv->token, &tc_cfg); + tc_cfg->enable = true; + if (tbl_profile->default_drop) { + tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP; + } else { + queue = dpaa2_flow_queue_action_to_queue(priv, tc_id, + tbl_profile->default_queue.index); + if (!queue) { + DPAA2_PMD_ERR("TC[%d] invalid default queue(%d)", + tc_id, tbl_profile->default_queue.index); + return -EINVAL; + } + tc_cfg->fs_miss_flow_id = queue->flow_id; + } + ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg); if (ret < 0) { DPAA2_PMD_ERR("TC[%d] FS configured failed", tc_id); return ret; @@ -4581,74 +3817,89 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, if (ret) return ret; +successful_config: + tbl_profile->enabled = true; + return 0; } + static int -dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, +dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, int rss_dist) { - struct dpaa2_key_extract *qos_extract; + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_flow_tbl_profile *tbl_profile; uint8_t *key_cfg_buf; - uint64_t key_cfg_iova; int ret; - struct dpni_qos_tbl_cfg qos_cfg; + struct dpni_qos_tbl_cfg *qos_cfg; struct fsl_mc_io *dpni = priv->hw; uint16_t entry_size; uint16_t key_max_size; + struct dpaa2_dev_flow *flow; if (!rss_dist && priv->num_rx_tc <= 1) { /* QoS table is effecitive for FS multiple TCs or RSS.*/ return 0; } - if (LIST_FIRST(&priv->flows)) { + flow = LIST_FIRST(&priv->flows); + while (flow) { + if (!flow->qos_flow) { + flow = LIST_NEXT(flow, next); + continue; + } + /** Clear existing QoS table if there is qos flow configured.*/ ret = dpni_clear_qos_table(dpni, CMD_PRI_LOW, priv->token); if (ret < 0) { - DPAA2_PMD_ERR("QoS table clear failed"); + DPAA2_PMD_ERR("QoS table clear failed(%d)", ret); return ret; } + priv->flow_profile.qos_profile.entry_num = 0; + memset(priv->flow_profile.qos_profile.entry_map, + 0, priv->qos_entries); + break; } - qos_extract = &priv->extract.qos_key_extract; - key_cfg_buf = priv->extract.qos_extract_param; - key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf, - DPAA2_EXTRACT_PARAM_MAX_SIZE); - if (key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, key_cfg_buf); + tbl_profile = &priv->flow_profile.qos_profile; + if (!tbl_profile->dpkg.num_extracts) + return 0; - return -ENOBUFS; - } + key_cfg_buf = priv->flow_profile.qos_profile.extract_param; - key_max_size = qos_extract->key_profile.key_max_size; + key_max_size = tbl_profile->key_profile.key_max_size; entry_size = dpaa2_flow_entry_size(key_max_size); - dpaa2_flow_qos_extracts_log(priv); + dpaa2_flow_extracts_log(priv, "Configure", MAX_TCS); - ret = dpkg_prepare_key_cfg(&qos_extract->dpkg, + ret = dpkg_prepare_key_cfg(&tbl_profile->dpkg, key_cfg_buf); if (ret < 0) { DPAA2_PMD_ERR("QoS prepare extract failed"); return ret; } - memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg)); - qos_cfg.keep_entries = true; - qos_cfg.key_cfg_iova = key_cfg_iova; + qos_cfg = &tbl_profile->qos_cfg; if (rss_dist) { - qos_cfg.discard_on_miss = true; + qos_cfg->discard_on_miss = true; } else { - qos_cfg.discard_on_miss = false; - qos_cfg.default_tc = 0; + qos_cfg->default_tc = tbl_profile->default_jump.group; + if (tbl_profile->default_drop) + qos_cfg->discard_on_miss = true; + else + qos_cfg->discard_on_miss = false; } - ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, - priv->token, &qos_cfg); + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + if (dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) + ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, priv->token, qos_cfg); + else + ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, qos_cfg); if (ret < 0) { - DPAA2_PMD_ERR("QoS table set failed"); + DPAA2_PMD_ERR("QoS table set failed(%d)", ret); return ret; } + tbl_profile->enabled = true; ret = dpaa2_flow_rule_add_all(priv, DPAA2_FLOW_QOS_TYPE, entry_size, 0); @@ -4698,207 +3949,299 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], } static int -dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) +dpaa2_flow_table_update(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type dist_type, uint8_t tc_id, int is_rss) { - const struct rte_flow_action_rss *rss_conf; - int is_keycfg_configured = 0, end_of_list = 0; - int ret = 0, i = 0, j = 0; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - uint16_t dist_size, key_size; - struct dpaa2_key_extract *qos_key_extract; - struct dpaa2_key_extract *tc_key_extract; - struct rte_dpaa2_flow_item *dpaa2_pattern = NULL; + int ret; - ret = dpaa2_flow_verify_attr(priv, attr); - if (ret) - return ret; + if (dist_type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_fs_rss_table_config(priv, tc_id, is_rss); + if (ret) + return ret; + } else if (dist_type == DPAA2_FLOW_QOS_TYPE) { + ret = dpaa2_flow_qos_table_config(priv, false); + if (ret) + return ret; + } else { + DPAA2_PMD_ERR("Invalid dist type(%d)!", dist_type); + return -EINVAL; + } - ret = dpaa2_flow_verify_action(priv, attr, actions); - if (ret) - return ret; + return 0; +} - ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, - priv->sp_protocol); - if (ret) - return ret; - /* Parse pattern list to get the matching parameters */ + +static int +dpaa2_flow_action_single_type_check(const struct rte_flow_action actions[], + enum rte_flow_action_type type) +{ + if (actions[0].type == type && + actions[1].type == RTE_FLOW_ACTION_TYPE_END) + return true; + + return false; +} + +static int +dpaa2_flow_qos_action_update(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *flow, + const struct rte_flow_action actions[], int new_flow) +{ + int end_of_list = 0, ret = 0, i = 0, set_jump = 0; + struct dpaa2_dev_flow_qos_action *qos_action; + + RTE_SET_USED(priv); + qos_action = &flow->flow_action.qos_action; + while (!end_of_list) { - switch (pattern[i].type) { - case RTE_FLOW_ITEM_TYPE_ETH: - ret = dpaa2_configure_flow_eth(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ETH flow config failed!"); - goto end_flow_set; - } + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_JUMP: + qos_action->action_jump_type = actions[i].type; + rte_memcpy(&qos_action->action_jump_cfg, actions[i].conf, + sizeof(struct rte_flow_action_jump)); + set_jump++; break; - case RTE_FLOW_ITEM_TYPE_VLAN: - ret = dpaa2_configure_flow_vlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_ERR("Invalid action[%d]'s type(%d)", + i, actions[i].type); + ret = -ENOTSUP; + goto end_action_set; + } + i++; + } + +end_action_set: + if (!set_jump && !ret && new_flow) + return -EINVAL; + + return ret; +} + +static int +dpaa2_flow_fs_action_update(struct dpaa2_dev_priv *priv, + struct dpaa2_generic_flow *fs_flow, + const struct rte_flow_action actions[]) +{ + int end_of_list = 0, ret = 0, i = 0; + union dpaa2_dev_flow_action flow_action_rollback; + + rte_memcpy(&flow_action_rollback, &fs_flow->flow_action, + sizeof(union dpaa2_dev_flow_action)); + memset(&fs_flow->flow_action, 0, sizeof(union dpaa2_dev_flow_action)); + + while (!end_of_list) { + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: + case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: + case RTE_FLOW_ACTION_TYPE_RSS: + ret = dpaa2_flow_fs_action_config(priv, fs_flow, &actions[i]); + if (ret) + goto end_action_set; + + break; + case RTE_FLOW_ACTION_TYPE_PF: + /* Skip this action, have to add for vxlan*/ + break; + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_ERR("Invalid action[%d]'s type(%d)", + i, actions[i].type); + ret = -ENOTSUP; + goto end_action_set; + } + i++; + } + +end_action_set: + if (ret || i < 1) { + rte_memcpy(&fs_flow->flow_action, &flow_action_rollback, + sizeof(union dpaa2_dev_flow_action)); + } + if (ret) + return ret; + + if (i < 1) { + DPAA2_PMD_ERR("No action is set!"); + return -EINVAL; + } + if (i > 2) { + DPAA2_PMD_WARN("Only last of %d actions is applied", + i - 1); + } + + return 0; +} + +static int +dpaa2_flow_generic_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], int is_rss, + enum dpaa2_flow_dist_type dist_type, int update) +{ + int extract_cfg = 0, end_of_list = 0; + int ret = 0, i = 0; + struct dpaa2_dev_priv *priv = flow->priv; + uint16_t key_size; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct rte_dpaa2_flow_item *dpaa2_pattern = NULL; + + ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, + priv->sp_protocol); + if (ret) + return ret; + + flow->ip_key = NET_PROT_NONE; + flow->ip_src = NET_PROT_NONE; + flow->ip_dst = NET_PROT_NONE; + + if (dist_type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[attr->group]; + + if (is_rss || (!is_rss && tbl_profile->is_rss)) { + RTE_ASSERT(dist_type == DPAA2_FLOW_FS_TYPE); + if (!update) { + dpaa2_flow_clean(priv->eth_dev, attr->group); + tbl_profile->rss_flow = NULL; + } + if (!is_rss) + tbl_profile->tc_cfg.dist_size = priv->dist_queues; + memset(&tbl_profile->dpkg, 0, + sizeof(struct dpkg_profile_cfg)); + memset(&tbl_profile->key_profile, 0, + sizeof(struct dpaa2_key_profile)); + } + + /* Parse pattern list to get the matching parameters */ + while (!end_of_list) { + switch (pattern[i].type) { + case RTE_FLOW_ITEM_TYPE_ETH: + ret = dpaa2_flow_eth_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); + if (ret) { + DPAA2_PMD_ERR("ETH flow config failed!"); + goto end_extract_set; + } + break; + case RTE_FLOW_ITEM_TYPE_VLAN: + ret = dpaa2_flow_vlan_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("vLan flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_IPV4: - ret = dpaa2_configure_flow_ipv4(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ipv4_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("IPV4 flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_IPV6: - ret = dpaa2_configure_flow_ipv6(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ipv6_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("IPV6 flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_ICMP: - ret = dpaa2_configure_flow_icmp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_icmp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("ICMP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_UDP: - ret = dpaa2_configure_flow_udp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_udp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("UDP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_TCP: - ret = dpaa2_configure_flow_tcp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_tcp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("TCP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_SCTP: - ret = dpaa2_configure_flow_sctp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_sctp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("SCTP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_ESP: - ret = dpaa2_configure_flow_esp(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_esp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("ESP flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_AH: - ret = dpaa2_configure_flow_ah(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ah_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("AH flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_GRE: - ret = dpaa2_configure_flow_gre(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_gre_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("GRE flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_vxlan_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_ecpri_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_GTP: - ret = dpaa2_configure_flow_gtp(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_gtp_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("GTP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_MPLS: - ret = dpaa2_configure_flow_mpls(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("MPLS flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_PPPOES: - ret = dpaa2_configure_flow_pppoe(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("PPPoE flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_RAW: - ret = dpaa2_configure_flow_raw(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); + ret = dpaa2_flow_raw_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); if (ret) { DPAA2_PMD_ERR("RAW flow config failed!"); - goto end_flow_set; + goto end_extract_set; } break; case RTE_FLOW_ITEM_TYPE_END: @@ -4908,164 +4251,104 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, DPAA2_PMD_ERR("Invalid flow item[%d] type(%d)", i, pattern[i].type); ret = -ENOTSUP; - break; + goto end_extract_set; } i++; } - qos_key_extract = &priv->extract.qos_key_extract; - key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); - - tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; - key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); - - /* Let's parse action on matching traffic */ - end_of_list = 0; - while (!end_of_list) { - switch (actions[j].type) { - case RTE_FLOW_ACTION_TYPE_QUEUE: - case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: - case RTE_FLOW_ACTION_TYPE_PORT_ID: - case RTE_FLOW_ACTION_TYPE_DROP: - ret = dpaa2_configure_flow_fs_action(priv, flow, - &actions[j]); - if (ret) - goto end_flow_set; - - /* Configure FS table first*/ - dist_size = priv->nb_rx_queues / priv->num_rx_tc; - if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_configure_fs_rss_table(priv, - flow->tc_id, - dist_size, - false); - if (ret) - goto end_flow_set; - } - - /* Configure QoS table then.*/ - if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_configure_qos_table(priv, false); - if (ret) - goto end_flow_set; - } - - if (priv->num_rx_tc > 1) { - ret = dpaa2_flow_add_qos_rule(priv, flow); - if (ret) - goto end_flow_set; - } + key_size = tbl_profile->key_profile.key_max_size; + flow->rule_cfg.key_size = dpaa2_flow_entry_size(key_size); - if (flow->tc_index >= priv->fs_entries) { - DPAA2_PMD_ERR("FS table with %d entries full", - priv->fs_entries); - return -1; - } + if (!extract_cfg) + goto end_extract_set; - ret = dpaa2_flow_add_fs_rule(priv, flow); - if (ret) - goto end_flow_set; + ret = dpaa2_flow_table_update(priv, dist_type, attr->group, is_rss); - break; - case RTE_FLOW_ACTION_TYPE_RSS: - rss_conf = actions[j].conf; - flow->action_type = RTE_FLOW_ACTION_TYPE_RSS; - - ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types, - &tc_key_extract->dpkg); - if (ret < 0) { - DPAA2_PMD_ERR("TC[%d] distset RSS failed", - flow->tc_id); - goto end_flow_set; - } +end_extract_set: + if (dpaa2_pattern) + rte_free(dpaa2_pattern); - dist_size = rss_conf->queue_num; - if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_configure_fs_rss_table(priv, - flow->tc_id, - dist_size, - true); - if (ret) - goto end_flow_set; - } + return ret; +} - if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_configure_qos_table(priv, true); - if (ret) - goto end_flow_set; - } +static inline int +dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv, + const struct rte_flow_attr *attr, uint32_t *pgroup_type, + uint32_t *pgroup_id) +{ + int ret = 0; + uint32_t group_id, group_type; - ret = dpaa2_flow_add_qos_rule(priv, flow); - if (ret) - goto end_flow_set; + group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr->group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group); + if (group_id >= priv->num_rx_tc && + group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + group_type = RTE_DPAA2_QOS_GROUP_FLOW; + group_id = DPAA2_FLOW_QOS_GROUP_ID; + } - ret = dpaa2_flow_add_fs_rule(priv, flow); - if (ret) - goto end_flow_set; + if (group_type == RTE_DPAA2_FS_GROUP_FLOW && !priv->fs_entries) { + DPAA2_PMD_ERR("No FS table created to support FS flow!"); + ret = -EINVAL; + goto complete_verify; + } - break; - case RTE_FLOW_ACTION_TYPE_PF: - /* Skip this action, have to add for vxlan */ - break; - case RTE_FLOW_ACTION_TYPE_END: - end_of_list = 1; - break; - default: - DPAA2_PMD_ERR("Invalid action type"); + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + if (attr->priority >= priv->qos_entries) { + DPAA2_PMD_ERR("Prior(%d) is out of range(%d)", + attr->priority, priv->qos_entries); ret = -ENOTSUP; - break; + goto complete_verify; } - j++; + goto complete_verify_group; } -end_flow_set: - if (!ret) { - /* New rules are inserted. */ - if (!curr) { - LIST_INSERT_HEAD(&priv->flows, flow, next); - } else { - while (LIST_NEXT(curr, next)) - curr = LIST_NEXT(curr, next); - LIST_INSERT_AFTER(curr, flow, next); + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW || + group_type == RTE_DPAA2_FS_GROUP_FLOW) { + if (group_id >= priv->num_rx_tc) { + DPAA2_PMD_ERR("Group(%d) is out of range(%d)", + group_id, priv->num_rx_tc); + ret = -ENOTSUP; + goto complete_verify; + } + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW && + (attr->priority + priv->fs_entries * group_id) >= priv->qos_entries) { + DPAA2_PMD_ERR("Prior(%d) + fs entries(%d) * group(%d) is out of range(%d)", + attr->priority, priv->fs_entries, group_id, + priv->qos_entries); + ret = -ENOTSUP; + goto complete_verify; } + } else { + DPAA2_PMD_ERR("Invalid group type(%d)", group_type); + ret = -EINVAL; + goto complete_verify; } - rte_free(dpaa2_pattern); - - return ret; -} - -static inline int -dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, - const struct rte_flow_attr *attr) -{ - int ret = 0; - - if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) { - DPAA2_PMD_ERR("Group/TC(%d) is out of range(%d)", - attr->group, dpni_attr->num_rx_tcs); - ret = -ENOTSUP; - } - if (unlikely(attr->priority >= dpni_attr->fs_entries)) { - DPAA2_PMD_ERR("Priority(%d) within group is out of range(%d)", - attr->priority, dpni_attr->fs_entries); - ret = -ENOTSUP; - } +complete_verify_group: if (unlikely(attr->egress)) { DPAA2_PMD_ERR("Egress flow configuration is not supported"); ret = -ENOTSUP; + goto complete_verify; } if (unlikely(!attr->ingress)) { DPAA2_PMD_ERR("Ingress flag must be configured"); ret = -EINVAL; } + +complete_verify: + if (!ret) { + if (pgroup_type) + *pgroup_type = group_type; + if (pgroup_id) + *pgroup_id = group_id; + } + return ret; } static inline int -dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], +dpaa2_flow_verify_patterns(const struct rte_flow_item pattern[], int sp_support) { unsigned int i, j, is_found = 0; @@ -5110,29 +4393,32 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], } static inline int -dpaa2_dev_verify_actions(const struct rte_flow_action actions[]) +dpaa2_flow_check_actions_support(const struct rte_flow_action actions[], + const enum rte_flow_action_type supported[], uint16_t len) { unsigned int i, j, is_found = 0; - int ret = 0; for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { - for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) { - if (dpaa2_supported_action_type[i] == actions[j].type) { + is_found = 0; + for (i = 0; i < len; i++) { + if (supported[i] == actions[j].type) { is_found = 1; break; } } - if (!is_found) { - ret = -ENOTSUP; - break; - } + if (!is_found) + return false; } for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP && - !actions[j].conf) - ret = -EINVAL; + !actions[j].conf) { + DPAA2_PMD_ERR("No config for actions[%d].type(%d)", + j, actions[j].type); + return false; + } } - return ret; + + return true; } static int @@ -5143,240 +4429,1371 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct dpni_attr dpni_attr; - struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; - uint16_t token = priv->token; + uint16_t supported_len = 0; int ret = 0; + uint32_t group_type; + const enum rte_flow_action_type *supported = NULL; + const char *err_str = NULL; + const void *cause = NULL; + enum rte_flow_error_type err_type = RTE_FLOW_ERROR_TYPE_NONE; - memset(&dpni_attr, 0, sizeof(struct dpni_attr)); - ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr); - if (ret < 0) { - DPAA2_PMD_ERR("Get dpni@%d attribute failed(%d)", - priv->hw_id, ret); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ATTR, - flow_attr, "invalid"); - return ret; + /* Verify input attributes */ + ret = dpaa2_flow_verify_attr(priv, flow_attr, &group_type, NULL); + if (ret) { + err_str = "Invalid attributes are given"; + cause = flow_attr; + err_type = RTE_FLOW_ERROR_TYPE_ATTR; + goto invalid_params; } - /* Verify input attributes */ - ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid attributes are given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ATTR, - flow_attr, "invalid"); - goto not_valid_params; - } - /* Verify input pattern list */ - ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid pattern list is given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ITEM, - pattern, "invalid"); - goto not_valid_params; + if (pattern) { + /* Verify input pattern list */ + ret = dpaa2_flow_verify_patterns(pattern, priv->sp_protocol); + if (ret) { + err_str = "Invalid pattern list is given"; + cause = pattern; + err_type = RTE_FLOW_ERROR_TYPE_ITEM; + goto invalid_params; + } } + /* Verify input action list */ - ret = dpaa2_dev_verify_actions(actions); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid action list is given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ACTION, - actions, "invalid"); - goto not_valid_params; + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW || + group_type == RTE_DPAA2_FS_GROUP_FLOW) { + supported = dpaa2_supported_fs_action_type; + supported_len = RTE_DIM(dpaa2_supported_fs_action_type); + } else { + supported = dpaa2_supported_qos_action_type; + supported_len = RTE_DIM(dpaa2_supported_qos_action_type); } -not_valid_params: + if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + err_str = "Invalid action list is given"; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION; + ret = -ENOTSUP; + goto invalid_params; + } + +invalid_params: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(error, -ret, err_type, cause, err_str); + return ret; } -static struct rte_flow * -dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) +static int +dpaa2_flow_is_ip_addr_extract(const struct dpkg_extract *extract) { - struct dpaa2_dev_flow *flow = NULL; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - int ret; - uint64_t iova; + enum dpkg_extract_type type = extract->type; + enum net_prot prot = extract->extract.from_hdr.prot; + uint32_t field = extract->extract.from_hdr.field; - dpaa2_flow_control_log = - getenv("DPAA2_FLOW_CONTROL_LOG"); - - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), - RTE_CACHE_LINE_SIZE); - if (!flow) { - DPAA2_PMD_ERR("Failure to allocate memory for flow"); - goto mem_failure; - } + if (type == DPKG_EXTRACT_FROM_HDR && prot == NET_PROT_IP && + (field == NH_FLD_IP_SRC || field == NH_FLD_IP_DST)) + return true; - /* Allocate DMA'ble memory to write the qos rules */ - flow->qos_key_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->qos_key_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_key_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for qos key(%p)", - __func__, flow->qos_key_addr); - goto mem_failure; - } - flow->qos_rule.key_iova = iova; + return false; +} - flow->qos_mask_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->qos_mask_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_mask_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for qos mask(%p)", - __func__, flow->qos_mask_addr); - goto mem_failure; - } - flow->qos_rule.mask_iova = iova; +static int +dpaa2_flow_ip_addr_extract_pos(uint32_t field, + const struct dpaa2_key_profile *profile) +{ + if (field != NH_FLD_IP_SRC && field != NH_FLD_IP_DST) + return -EINVAL; + if (profile->ip_addr_extracts[0].field == field) + return 0; + else if (profile->ip_addr_extracts[1].field == field) + return 1; + else + return -ENXIO; +} - /* Allocate DMA'ble memory to write the FS rules */ - flow->fs_key_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->fs_key_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_key_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for fs key(%p)", - __func__, flow->fs_key_addr); - goto mem_failure; - } - flow->fs_rule.key_iova = iova; +static int +dpaa2_flow_key_offset_size(struct dpaa2_dev_flow *flow, + struct dpaa2_flow_tbl_profile *tbl_profile, uint8_t idx, + uint8_t *offset, uint8_t *size, + enum dpaa2_flow_dist_type type) +{ + struct dpkg_profile_cfg *dpkg = &tbl_profile->dpkg; + struct dpaa2_key_profile *profile = &tbl_profile->key_profile; + int pos, prev_ip_addr_pos; + uint32_t field; + uint8_t ip_addr_size = 0, ip_addr_offset = 0; + struct dpaa2_generic_flow *_flow; - flow->fs_mask_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->fs_mask_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_mask_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for fs mask(%p)", - __func__, flow->fs_mask_addr); - goto mem_failure; - } - flow->fs_rule.mask_iova = iova; + _flow = type == DPAA2_FLOW_QOS_TYPE ? flow->qos_flow : flow->fs_flow; - priv->curr = flow; + if (_flow->ip_key == NET_PROT_IPV4) + ip_addr_size = NH_FLD_IPV4_ADDR_SIZE; + else if (_flow->ip_key == NET_PROT_IPV6) + ip_addr_size = NH_FLD_IPV6_ADDR_SIZE; - ret = dpaa2_generic_flow_set(flow, dev, attr, pattern, actions, error); - if (ret < 0) { - if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - attr, "unknown"); - DPAA2_PMD_ERR("Create flow failed (%d)", ret); - goto creation_error; + field = dpkg->extracts[idx].extract.from_hdr.field; + prev_ip_addr_pos = dpaa2_extract_prev_ip_addr_pos(profile); + if (prev_ip_addr_pos >= 0) { + ip_addr_offset = + profile->key_offset[prev_ip_addr_pos] + + profile->key_size[prev_ip_addr_pos]; } - priv->curr = NULL; - return (struct rte_flow *)flow; - -mem_failure: - rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "memory alloc"); - -creation_error: - if (flow) { - rte_free(flow->qos_key_addr); - rte_free(flow->qos_mask_addr); - rte_free(flow->fs_key_addr); - rte_free(flow->fs_mask_addr); - rte_free(flow); + if (dpaa2_flow_is_ip_addr_extract(&dpkg->extracts[idx])) { + pos = dpaa2_flow_ip_addr_extract_pos(field, profile); + if (!ip_addr_size) + return -EINVAL; + *offset = ip_addr_offset + ip_addr_size * pos; + *size = ip_addr_size; + } else { + *offset = profile->key_offset[idx]; + *size = profile->key_size[idx]; } - priv->curr = NULL; - return NULL; + return 0; } static int -dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, - struct rte_flow_error *error) +dpaa2_flow_rule_data_valid(struct dpaa2_dev_flow *flow, + uint8_t key_offset, uint8_t key_size, + enum dpaa2_flow_dist_type type) { - int ret = 0; - struct dpaa2_dev_flow *flow; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; + uint8_t *mask, i; + int valid = 0; + struct dpaa2_generic_flow *_flow; - flow = (struct dpaa2_dev_flow *)_flow; + _flow = type == DPAA2_FLOW_QOS_TYPE ? flow->qos_flow : flow->fs_flow; + mask = _flow->mask_addr + key_offset; - switch (flow->action_type) { - case RTE_FLOW_ACTION_TYPE_QUEUE: - case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: - case RTE_FLOW_ACTION_TYPE_PORT_ID: - case RTE_FLOW_ACTION_TYPE_DROP: - if (priv->num_rx_tc > 1) { - /* Remove entry from QoS table first */ - ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, - priv->token, - &flow->qos_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove FS QoS entry failed"); - dpaa2_flow_qos_entry_log("Delete failed", flow, - -1); - abort(); - goto error; - } + for (i = 0; i < key_size; i++) { + if (mask[i]) { + valid = 1; + break; } + } + + return valid; +} + +static void +dpaa2_flow_remove_invalid_rule_data(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type type, uint8_t tc_id, + uint8_t key_offset, uint8_t key_size) +{ + struct dpaa2_dev_flow *flow, *next; + struct dpaa2_generic_flow *_flow; + + flow = LIST_FIRST(&priv->flows); + while (flow) { + next = LIST_NEXT(flow, next); + if (type == DPAA2_FLOW_QOS_TYPE) { + _flow = flow->qos_flow; + if (!_flow) + goto skip_update_flow; + } else { + _flow = flow->fs_flow; + if (!_flow) + goto skip_update_flow; + if (_flow->tc_id != tc_id) + goto skip_update_flow; + } + + if (key_offset < _flow->rule_size) { + memmove(_flow->key_addr + key_offset, + _flow->key_addr + key_offset + key_size, + _flow->rule_size - (key_offset + key_size)); + memmove(_flow->mask_addr + key_offset, + _flow->mask_addr + key_offset + key_size, + _flow->rule_size - (key_offset + key_size)); + _flow->rule_size -= key_size; + } + if (_flow->rule_cfg.key_size > _flow->rule_size) { + memset(_flow->key_addr + _flow->rule_size, 0, + _flow->rule_cfg.key_size - _flow->rule_size); + memset(_flow->mask_addr + _flow->rule_size, 0, + _flow->rule_cfg.key_size - _flow->rule_size); + } + +skip_update_flow: + flow = next; + } +} + +static int +dpaa2_flow_remove_invalid_extract(struct rte_eth_dev *dev, + enum dpaa2_flow_dist_type type, uint8_t tc_id) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *flow, *next; + uint8_t i, key_offset, key_size, j, remove_conut = 0; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpkg_profile_cfg *dpkg; + struct dpaa2_key_profile *key_profile; + int valid[DPKG_MAX_NUM_OF_EXTRACTS], update = 0, ret, ipaddr; + enum net_prot prot; + uint32_t field, start, end; + uint32_t ip_src_size, ip_dst_size; + struct dpaa2_generic_flow *_flow; + + if (type == DPAA2_FLOW_QOS_TYPE && + priv->num_rx_tc <= 1) { + /** No QoS table.*/ + return 0; + } + + if (type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + + dpkg = &tbl_profile->dpkg; + key_profile = &tbl_profile->key_profile; + for (i = 0; i < key_profile->num; i++) { + valid[i] = 0; + flow = LIST_FIRST(&priv->flows); + while (flow) { + next = LIST_NEXT(flow, next); + _flow = type == DPAA2_FLOW_QOS_TYPE ? + flow->qos_flow : flow->fs_flow; + if (!_flow) + goto skip_validation; + + if (type == DPAA2_FLOW_FS_TYPE && + _flow->tc_id != tc_id) + goto skip_validation; + + key_offset = 0; + key_size = 0; + + ret = dpaa2_flow_key_offset_size(flow, tbl_profile, i, + &key_offset, &key_size, type); + if (ret) + goto skip_validation; + + if (dpaa2_flow_rule_data_valid(flow, + key_offset, key_size, type)) { + valid[i] = 1; + break; + } +skip_validation: + flow = next; + } + if (!valid[i]) + remove_conut++; + } + + if (remove_conut > 0) { + if (type == DPAA2_FLOW_QOS_TYPE) { + dpaa2_flow_extracts_log(priv, + "Before removing extract(s)", MAX_TCS); + } else { + dpaa2_flow_extracts_log(priv, + "Before removing extract(s)", tc_id); + } + } else { + return 0; + } + + i = key_profile->num - 1; + while (remove_conut) { + if (valid[i]) { + if (i == 0) { + DPAA2_PMD_ERR("Fatal: %d key(s) not removed!", + remove_conut); + return -EINVAL; + } + i--; + continue; + } + key_size = key_profile->key_size[i]; + key_offset = key_profile->key_offset[i]; + + for (j = i + 1; j < key_profile->num; j++) + key_profile->key_offset[j] -= key_size; + + ipaddr = 0; + if (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR) { + prot = dpkg->extracts[i].extract.from_hdr.prot; + field = dpkg->extracts[i].extract.from_hdr.field; + ipaddr = dpaa2_flow_ip_address_extract(prot, field); + } + if (!ipaddr) + update += key_size; + + if ((i + 1) < key_profile->num) { + memmove(&key_profile->key_offset[i], + &key_profile->key_offset[i + 1], + key_profile->num - i - 1); + memmove(&key_profile->key_size[i], + &key_profile->key_size[i + 1], + key_profile->num - i - 1); + memmove(&key_profile->prot_field[i], + &key_profile->prot_field[i + 1], + (key_profile->num - i - 1) * + sizeof(struct key_prot_field)); + + memmove(&dpkg->extracts[i], &dpkg->extracts[i + 1], + (key_profile->num - i - 1) * + sizeof(struct dpkg_extract)); + } + + dpaa2_flow_remove_invalid_rule_data(priv, type, tc_id, + key_offset, key_size); + + key_profile->num--; + dpkg->num_extracts--; + i--; + remove_conut--; + }; + + key_profile->key_max_size -= update; + key_profile->key_max_size -= + (key_profile->ip_addr_extracts[0].max_size + + key_profile->ip_addr_extracts[1].max_size); + + key_profile->l4_sp_present = 0; + key_profile->l4_dp_present = 0; + memset(key_profile->ip_addr_extracts, 0, + sizeof(struct dpaa2_ip_addr_extract) * 2); + + if (key_profile->num >= 2) + start = key_profile->num - 2; + else if (key_profile->num >= 1) + start = key_profile->num - 1; + else + goto skip_ip_addr_extract; + end = key_profile->num; + + j = 0; + for (i = start; i < end; i++) { + if (dpaa2_flow_is_ip_addr_extract(&dpkg->extracts[i])) { + key_profile->ip_addr_extracts[j].field = + dpkg->extracts[i].extract.from_hdr.field; + key_profile->ip_addr_extracts[j].max_size = + sizeof(rte_be32_t); + j++; + } + } + ip_src_size = sizeof(rte_be32_t); + ip_dst_size = sizeof(rte_be32_t); + flow = LIST_FIRST(&priv->flows); + while (flow) { + next = LIST_NEXT(flow, next); + _flow = type == DPAA2_FLOW_QOS_TYPE ? + flow->qos_flow : flow->fs_flow; + if (!_flow) + goto next_flow; + + if (type == DPAA2_FLOW_FS_TYPE && + _flow->tc_id != tc_id) + goto next_flow; + + if (_flow->ip_key == NET_PROT_IPV6) { + if (_flow->ip_src == NET_PROT_IPV6) + ip_src_size = NH_FLD_IPV6_ADDR_SIZE; + if (_flow->ip_dst == NET_PROT_IPV6) + ip_dst_size = NH_FLD_IPV6_ADDR_SIZE; + } + +next_flow: + flow = next; + } + if (key_profile->ip_addr_extracts[0].field == NH_FLD_IP_SRC) + key_profile->ip_addr_extracts[0].max_size = ip_src_size; + else if (key_profile->ip_addr_extracts[0].field == NH_FLD_IP_DST) + key_profile->ip_addr_extracts[0].max_size = ip_dst_size; + + if (key_profile->ip_addr_extracts[1].field == NH_FLD_IP_SRC) + key_profile->ip_addr_extracts[1].max_size = ip_src_size; + else if (key_profile->ip_addr_extracts[1].field == NH_FLD_IP_DST) + key_profile->ip_addr_extracts[1].max_size = ip_dst_size; + + key_profile->key_max_size += + (key_profile->ip_addr_extracts[0].max_size + + key_profile->ip_addr_extracts[1].max_size); + +skip_ip_addr_extract: + for (i = 0; i < dpkg->num_extracts; i++) { + if ((dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_TCP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_TCP_PORT_SRC) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_UDP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_UDP_PORT_SRC) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_SCTP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_SCTP_PORT_SRC)) { + key_profile->l4_sp_present = 1; + key_profile->l4_sp_extract_idx = i; + key_profile->l4_sp_key_offset = + key_profile->key_offset[i]; + } else if ((dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_TCP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_TCP_PORT_DST) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_UDP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_UDP_PORT_DST) || + (dpkg->extracts[i].type == DPKG_EXTRACT_FROM_HDR && + dpkg->extracts[i].extract.from_hdr.prot == + NET_PROT_SCTP && + dpkg->extracts[i].extract.from_hdr.field == + NH_FLD_SCTP_PORT_DST)) { + key_profile->l4_dp_present = 1; + key_profile->l4_dp_extract_idx = i; + key_profile->l4_dp_key_offset = + key_profile->key_offset[i]; + } + } + + if (type == DPAA2_FLOW_QOS_TYPE) { + dpaa2_flow_extracts_log(priv, + "After removing extract(s)", MAX_TCS); + } else { + dpaa2_flow_extracts_log(priv, + "After removing extract(s)", tc_id); + } + + return update; +} + +static int +dpaa2_flow_remove_generic_entry(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, enum dpaa2_flow_dist_type type) +{ + int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_dev_flow_fs_action *fs_action; + uint8_t tc_id; + + if (type == DPAA2_FLOW_QOS_TYPE) + goto remove_qos_flow; + + fs_action = &flow->flow_action.fs_action; + tc_id = flow->tc_id; + switch (fs_action->action_type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: + case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: /* Then remove entry from FS table */ ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token, - flow->tc_id, &flow->fs_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove entry from FS[%d] failed", - flow->tc_id); - goto error; + flow->tc_id, &flow->rule_cfg); + if (ret) { + DPAA2_PMD_ERR("Remove entry from FS[%d] failed(%d)", + flow->tc_id, ret); + dpaa2_flow_fs_entry_log("Delete failed", flow); + } else { + dpaa2_flow_fs_entry_log("Delete success", flow); + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + tbl_profile->entry_num--; + dpaa2_flow_entry_map_set(tbl_profile->entry_map, + flow->entry_index, 0); } break; case RTE_FLOW_ACTION_TYPE_RSS: - if (priv->num_rx_tc > 1) { - ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, - priv->token, - &flow->qos_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove RSS QoS entry failed"); - goto error; - } - } + /** Remove QoS entry later.*/ break; default: - DPAA2_PMD_ERR("Action(%d) not supported", flow->action_type); + DPAA2_PMD_ERR("Action(%d) not supported", + fs_action->action_type); ret = -ENOTSUP; break; } - LIST_REMOVE(flow, next); - rte_free(flow->qos_key_addr); - rte_free(flow->qos_mask_addr); - rte_free(flow->fs_key_addr); - rte_free(flow->fs_mask_addr); - /* Now free the flow */ - rte_free(flow); + return ret; -error: +remove_qos_flow: + if (priv->num_rx_tc > 1) { + /* Remove entry from QoS table first */ + ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, + priv->token, &flow->rule_cfg); + if (ret) { + DPAA2_PMD_ERR("Remove QoS entry failed(%d)", ret); + dpaa2_flow_qos_entry_log("Delete failed", flow); + /** Will not remove FS entry.*/ + } else { + dpaa2_flow_qos_entry_log("Delete success", flow); + tbl_profile = &priv->flow_profile.qos_profile; + tbl_profile->entry_num--; + dpaa2_flow_entry_map_set(tbl_profile->entry_map, + flow->entry_index, 0); + } + } + + return ret; +} + +static int +dpaa2_flow_generic_flow_destroy(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, enum dpaa2_flow_dist_type type) +{ + int ret = 0, update; + uint8_t tc_id = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + dpaa2_dump_extract_map(priv, "Start destroying flow", type, + type == DPAA2_FLOW_FS_TYPE ? flow->tc_id : 0); + + ret = dpaa2_flow_remove_generic_entry(dev, flow, type); if (ret) - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, "unknown"); + return ret; + + if (type == DPAA2_FLOW_FS_TYPE) + tc_id = flow->tc_id; + + update = dpaa2_flow_remove_invalid_extract(dev, type, tc_id); + if (update > 0) { + if (type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_fs_rss_table_config(priv, + flow->tc_id, false); + if (ret) + DPAA2_PMD_ERR("Re-configure FS table failed(%d)", ret); + } else { + ret = dpaa2_flow_qos_table_config(priv, false); + if (ret) + DPAA2_PMD_ERR("Re-configure QoS table failed(%d)", ret); + } + } + + if (!ret) { + dpaa2_dump_extract_map(priv, "End destroying flow", + type, tc_id); + } + return ret; } +static int +dpaa2_flow_qos_fs_action_set(const struct rte_flow_action actions[], + struct rte_flow_action qos_actions[], + struct rte_flow_action fs_actions[], + uint8_t *qos_action_num, uint8_t *fs_action_num) +{ + uint8_t qos_act_num = 0, fs_act_num = 0; + int end_of_list = 0, i = 0, is_qos_act, is_fs_act; + struct rte_flow_action action_check[2]; + + action_check[1].type = RTE_FLOW_ACTION_TYPE_END; + while (!end_of_list) { + if (actions[i].type == RTE_FLOW_ACTION_TYPE_END) { + if (qos_action_num) + *qos_action_num = qos_act_num; + if (fs_action_num) + *fs_action_num = fs_act_num; + qos_actions[qos_act_num].type = actions[i].type; + fs_actions[fs_act_num].type = actions[i].type; + end_of_list = 1; + continue; + } + action_check[0].type = actions[i].type; + action_check[0].conf = actions[i].conf; + is_qos_act = dpaa2_flow_check_actions_support(action_check, + dpaa2_supported_qos_action_type, + RTE_DIM(dpaa2_supported_qos_action_type)); + is_fs_act = dpaa2_flow_check_actions_support(action_check, + dpaa2_supported_fs_action_type, + RTE_DIM(dpaa2_supported_fs_action_type)); + if (!is_qos_act && !is_fs_act) + return -EINVAL; + if (is_qos_act && is_fs_act) + is_qos_act = false; + if (is_qos_act) { + qos_actions[qos_act_num].type = actions[i].type; + qos_actions[qos_act_num].conf = actions[i].conf; + qos_act_num++; + } + if (is_fs_act) { + fs_actions[fs_act_num].type = actions[i].type; + fs_actions[fs_act_num].conf = actions[i].conf; + fs_act_num++; + } + i++; + } + + return 0; +} + +static struct dpaa2_generic_flow * +dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error, enum dpaa2_flow_dist_type type, + int mix_extract, int is_rss) +{ + struct dpaa2_generic_flow *flow = NULL; + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret, idx = -1; + uint64_t iova, mc_rev; + uint8_t qos_action_num = 0, fs_action_num = 0; + struct rte_flow_action qos_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + struct rte_flow_action fs_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + struct rte_flow_action_jump action_jump; + const struct rte_flow_action_rss *action_rss; + const struct rte_flow_action_queue *action_q; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_queue *dir_rxq = NULL; + + if (type != DPAA2_FLOW_QOS_TYPE && type != DPAA2_FLOW_FS_TYPE) + return NULL; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + mc_rev = dpaa2_dev->bus_info->mc_rev; + + if (actions) { + ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions, + fs_actions, &qos_action_num, &fs_action_num); + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to set qos/fs actions!", ret); + goto creation_error; + } + if (type == DPAA2_FLOW_QOS_TYPE && + dpaa2_flow_action_single_type_check(fs_actions, + RTE_FLOW_ACTION_TYPE_QUEUE)) { + action_q = fs_actions[0].conf; + if (action_q->index >= dev->data->nb_rx_queues) { + DPAA2_PMD_ERR("direct queue index(%d) >= max(%d)", + action_q->index, + dev->data->nb_rx_queues); + ret = -EINVAL; + goto creation_error; + } + if ((mc_rev < DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV || + mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) && + mix_extract) { + /** We don't recommend steering flow by QoS table here + * because this version doesn't support QoS flow HW update + * and QoS table miss flow. + */ + dir_rxq = NULL; + } else { + dir_rxq = dev->data->rx_queues[action_q->index]; + } + } + } + + if (type == DPAA2_FLOW_FS_TYPE && attr) { + if (attr->group >= priv->num_rx_tc) { + DPAA2_PMD_ERR("Flow group(%d) >= max(%d)", + attr->group, priv->num_rx_tc); + return NULL; + } + if (attr->priority >= priv->fs_entries && !is_rss) { + DPAA2_PMD_ERR("FS[%d].entry(%d) >= max(%d)", + attr->group, attr->priority, priv->fs_entries); + return NULL; + } + } + + if (dir_rxq) { + qos_actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + qos_actions[0].conf = &action_jump; + qos_actions[1].type = RTE_FLOW_ACTION_TYPE_END; + /** Ignore attr->group*/ + if ((mix_extract || type == DPAA2_FLOW_FS_TYPE) && + attr->group < priv->num_rx_tc && + attr->group != dir_rxq->tc_index) { + DPAA2_PMD_ERR("Attribute group(%d) conflicts with dest queue's TC(%d)", + attr->group, dir_rxq->tc_index); + return NULL; + } + action_jump.group = dir_rxq->tc_index; + if (attr->group >= priv->num_rx_tc) + idx = attr->priority; + else if (!priv->fs_entries) + idx = action_jump.group * priv->dist_queues + attr->priority; + else + idx = action_jump.group * priv->fs_entries + attr->priority; + } else if (mix_extract && type == DPAA2_FLOW_QOS_TYPE) { + /** Move end action.*/ + rte_memcpy(&qos_actions[qos_action_num + 1], + &qos_actions[qos_action_num], + sizeof(struct rte_flow_action)); + /** Jump to FS[group]*/ + qos_actions[qos_action_num].type = RTE_FLOW_ACTION_TYPE_JUMP; + qos_actions[qos_action_num].conf = &action_jump; + action_jump.group = attr->group; + idx = action_jump.group * priv->fs_entries + attr->priority; + qos_action_num++; + } else if (!mix_extract && type == DPAA2_FLOW_QOS_TYPE) { + if (!qos_action_num) { + DPAA2_PMD_ERR("No QoS flow's action!"); + return NULL; + } + if (!is_rss) { + idx = dpaa2_flow_acquire_entry_idx(priv, attr->priority, + DPAA2_FLOW_QOS_TYPE, attr->group); + } + } else if (type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_verify_fs_action(priv, attr, actions); + if (ret) + return NULL; + if (!is_rss) { + idx = dpaa2_flow_acquire_entry_idx(priv, attr->priority, + DPAA2_FLOW_FS_TYPE, attr->group); + } + } else { + DPAA2_PMD_ERR("Invalid flow type(%d) or extract type(%d)", + type, mix_extract); + return NULL; + } + if (idx < 0 && !is_rss) + return NULL; + if (idx >= 0 && idx < RTE_ETH_DCB_NUM_USER_PRIORITIES && !is_rss && + type == DPAA2_FLOW_QOS_TYPE && priv->dcb_flow[idx]) { + DPAA2_PMD_ERR("QoS flow[%d] added conflicts with dcb flow", idx); + return NULL; + } + + if (!is_rss) { + ret = dpaa2_flow_verify_entry(priv, attr->group, idx, type); + if (ret) + return NULL; + if ((type == DPAA2_FLOW_QOS_TYPE && idx >= priv->qos_entries) || + (type == DPAA2_FLOW_FS_TYPE && idx >= priv->fs_entries)) { + DPAA2_PMD_ERR("%s flow[%d] added more than max entries(%d)", + type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", idx, + type == DPAA2_FLOW_QOS_TYPE ? priv->qos_entries : priv->fs_entries); + return NULL; + } + } + + dpaa2_dump_extract_map(priv, "Start creating flow", + type, attr->group); + + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_generic_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + DPAA2_PMD_ERR("Failure to allocate memory for flow"); + goto mem_failure; + } + flow->priv = priv; + + /* Allocate DMA'ble memory to write the qos rules */ + flow->key_addr = rte_zmalloc(NULL, + DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); + if (!flow->key_addr) { + DPAA2_PMD_ERR("Memory allocation failed"); + goto mem_failure; + } + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->key_addr, + DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + if (iova == RTE_BAD_IOVA) { + DPAA2_PMD_ERR("%s: No IOMMU map for key(%p)", + __func__, flow->key_addr); + goto mem_failure; + } + flow->rule_cfg.key_iova = iova; + + flow->mask_addr = rte_zmalloc(NULL, + DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); + if (!flow->mask_addr) { + DPAA2_PMD_ERR("Memory allocation failed"); + goto mem_failure; + } + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->mask_addr, + DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + if (iova == RTE_BAD_IOVA) { + DPAA2_PMD_ERR("%s: No IOMMU map for mask(%p)", + __func__, flow->mask_addr); + goto mem_failure; + } + flow->rule_cfg.mask_iova = iova; + + flow->ip_key = NET_PROT_NONE; + + priv->cur_flow = flow; + if (is_rss) { + action_rss = actions[0].conf; + tbl_profile = &priv->flow_profile.tc_profile[attr->group]; + tbl_profile->tc_cfg.dist_size = action_rss->queue_num; + } + ret = dpaa2_flow_generic_extract_rule_set(flow, + attr, pattern, is_rss, type, false); + if (ret < 0) { + if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) { + rte_flow_error_set(error, EPERM, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + attr, "unknown"); + } + DPAA2_PMD_ERR("Create %s flow failed (%d)", + type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", ret); + goto creation_error; + } + + flow->entry_index = idx; + if (type == DPAA2_FLOW_QOS_TYPE) { + ret = dpaa2_flow_qos_action_update(priv, flow, qos_actions, true); + if (ret) + goto creation_error; + if (dir_rxq) { + flow->direct_queue = true; + flow->flow_id = dir_rxq->flow_id; + } + ret = dpaa2_flow_add_qos_rule(priv, flow); + if (ret) + goto creation_error; + } else { + flow->tc_id = attr->group; + ret = dpaa2_flow_fs_action_update(priv, flow, fs_actions); + if (ret) + goto creation_error; + if (!is_rss) { + ret = dpaa2_flow_add_fs_rule(priv, flow); + if (ret) + goto creation_error; + } else { + flow->is_rss = true; + } + } + priv->cur_flow = NULL; + + dpaa2_dump_extract_map(priv, "Complete creating flow", + type, attr->group); + + return flow; + +mem_failure: + rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "memory alloc"); + +creation_error: + if (flow) { + if (flow->key_addr) + rte_free(flow->key_addr); + if (flow->mask_addr) + rte_free(flow->mask_addr); + rte_free(flow); + } + + return NULL; +} + + +static struct rte_flow * +dpaa2_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct dpaa2_dev_flow *flow = NULL, *curr; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret, is_rss = false; + struct dpaa2_generic_flow *qos_flow = NULL; + struct dpaa2_generic_flow *fs_flow = NULL; + uint32_t group_id, group_type; + const struct rte_flow_action_rss *rss_conf; + struct rte_flow_item items[DPKG_MAX_NUM_OF_EXTRACTS + 1]; + int rss_item = false, err_code = 0; + uint8_t spec_buf[1024]; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + struct rte_flow_attr local_attr; + + if (getenv("DPAA2_FLOW_CONTROL_LOG")) + dpaa2_flow_control_log = 1; + + group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr->group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group); + if (group_id >= priv->num_rx_tc && + group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + group_type = RTE_DPAA2_QOS_GROUP_FLOW; + group_id = DPAA2_FLOW_QOS_GROUP_ID; + } + rte_memcpy(&local_attr, attr, sizeof(struct rte_flow_attr)); + local_attr.group = group_id; + + if (actions) { + is_rss = dpaa2_flow_action_single_type_check(actions, + RTE_FLOW_ACTION_TYPE_RSS); + } + if (is_rss && group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + err_str = "RSS doesn't supports QoS table!"; + error_type = RTE_FLOW_ERROR_TYPE_ATTR; + err_code = -EINVAL; + goto flow_failure; + } + if (is_rss && group_type != RTE_DPAA2_FS_GROUP_FLOW) { + DPAA2_PMD_WARN("RSS distribution in TC%d.", group_id); + group_type = RTE_DPAA2_FS_GROUP_FLOW; + } + if (is_rss && !pattern) { + rss_conf = actions[0].conf; + ret = dpaa2_flow_rss_conf_to_item(rss_conf->types, items, + spec_buf, 1024); + if (ret < 0) { + DPAA2_PMD_ERR("TC[%d] converts to RSS items failed(%d)", + group_id, ret); + error_type = RTE_FLOW_ERROR_TYPE_ITEM; + err_code = ret; + err_str = "Failed to converts RSS config type to RSS items!"; + goto flow_failure; + } + rss_item = true; + } + + + DPAA2_PMD_DEBUG("Port %s-%s: group type:%d, group id:%d, total RX TCs:%d", + dev->data->name, __func__, group_type, group_id, priv->num_rx_tc); + if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + if (priv->qos_entries > 0) { + qos_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern, + actions, error, DPAA2_FLOW_QOS_TYPE, true, is_rss); + if (!qos_flow) { + err_str = "Failed to create QoS flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } + if (priv->fs_entries > 0 && !(qos_flow && qos_flow->direct_queue)) { + fs_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern, + actions, error, DPAA2_FLOW_FS_TYPE, true, is_rss); + if (!fs_flow) { + if (qos_flow) { + ret = dpaa2_flow_generic_flow_destroy(dev, qos_flow, + DPAA2_FLOW_QOS_TYPE); + if (ret) { + DPAA2_PMD_ERR("%s: QoS flow destroy failed(%d)!", + __func__, ret); + } + } + err_str = "Failed to create FS flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } + } else if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + if (!priv->qos_entries) { + err_str = "No QoS entry available!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + qos_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, pattern, + actions, error, DPAA2_FLOW_QOS_TYPE, false, is_rss); + if (!qos_flow) { + err_str = "QoS flow create failed!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } else if (group_type == RTE_DPAA2_FS_GROUP_FLOW) { + if (!priv->fs_entries && !is_rss) { + err_str = "No FS entry available!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + fs_flow = dpaa2_flow_generic_flow_create(dev, &local_attr, + rss_item ? items : pattern, + actions, error, DPAA2_FLOW_FS_TYPE, false, is_rss); + if (!fs_flow) { + err_str = "FS flow create failed!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + } else { + err_str = "Invalid flow attribut parameter!"; + error_type = RTE_FLOW_ERROR_TYPE_ATTR; + err_code = -EINVAL; + goto flow_failure; + } + if (!qos_flow && !fs_flow) { + err_str = "Both QoS flow and FS flow are NULL!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + err_str = "Failure to allocate memory for flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -ENOMEM; + goto flow_failure; + } + flow->qos_flow = qos_flow; + flow->fs_flow = fs_flow; + flow->priv = priv; + if (fs_flow && fs_flow->is_rss) + priv->flow_profile.tc_profile[group_id].rss_flow = flow; + + /* New rules are inserted. */ + curr = LIST_FIRST(&priv->flows); + if (!curr) { + LIST_INSERT_HEAD(&priv->flows, flow, next); + } else { + while (LIST_NEXT(curr, next)) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, flow, next); + } + + return (struct rte_flow *)flow; + +flow_failure: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(error, -err_code, error_type, NULL, err_str); + + if (flow) { + if (flow->qos_flow && flow->qos_flow->key_addr) + rte_free(flow->qos_flow->key_addr); + if (flow->qos_flow && flow->qos_flow->mask_addr) + rte_free(flow->qos_flow->mask_addr); + if (flow->fs_flow && flow->fs_flow->key_addr) + rte_free(flow->fs_flow->key_addr); + if (flow->fs_flow && flow->fs_flow->mask_addr) + rte_free(flow->fs_flow->mask_addr); + if (flow->qos_flow) + rte_free(flow->qos_flow); + if (flow->fs_flow) + rte_free(flow->fs_flow); + rte_free(flow); + } + priv->cur_flow = NULL; + + return NULL; +} + + +static int +dpaa2_flow_destroy(struct rte_eth_dev *dev, + struct rte_flow *_flow, struct rte_flow_error *error) +{ + int qos_ret = 0, fs_ret = 0; + struct dpaa2_dev_flow *flow; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile; + uint8_t tc_id; + + RTE_SET_USED(error); + + flow = (struct dpaa2_dev_flow *)_flow; + + LIST_REMOVE(flow, next); + + if (flow->qos_flow) { + qos_ret = dpaa2_flow_generic_flow_destroy(dev, flow->qos_flow, + DPAA2_FLOW_QOS_TYPE); + if (qos_ret) { + DPAA2_PMD_ERR("%s: destroy QoS flow failed(%d)", + __func__, qos_ret); + } + if (flow->qos_flow->key_addr) + rte_free(flow->qos_flow->key_addr); + if (flow->qos_flow->mask_addr) + rte_free(flow->qos_flow->mask_addr); + rte_free(flow->qos_flow); + flow->qos_flow = NULL; + } + if (flow->fs_flow) { + fs_ret = dpaa2_flow_generic_flow_destroy(dev, flow->fs_flow, + DPAA2_FLOW_FS_TYPE); + if (fs_ret) { + DPAA2_PMD_ERR("%s: destroy FS flow failed(%d)", + __func__, fs_ret); + } + if (flow->fs_flow->key_addr) + rte_free(flow->fs_flow->key_addr); + if (flow->fs_flow->mask_addr) + rte_free(flow->fs_flow->mask_addr); + if (flow->fs_flow->is_rss) { + tc_id = flow->fs_flow->tc_id; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + tbl_profile->rss_flow = NULL; + } + rte_free(flow->fs_flow); + flow->fs_flow = NULL; + } + rte_free(flow); + + if (!qos_ret && !fs_ret) + return 0; + + return qos_ret ? qos_ret : fs_ret; +} + + +static int +dpaa2_flow_actions_update(struct rte_eth_dev *dev, + struct rte_flow *_flow, + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *flow; + struct dpaa2_flow_tbl_profile *tbl_profile = NULL; + int ret = 0, is_rss = false, hw_update = false, err_code = 0, qos_direct; + struct dpaa2_dev_flow_fs_action *fs_action; + uint8_t qos_action_num = 0, fs_action_num = 0, tc_id; + struct rte_flow_action qos_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + struct rte_flow_action fs_actions[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + const struct rte_flow_action_rss *rss_conf; + struct rte_flow_action_jump jump_conf; + struct rte_flow_item items[DPKG_MAX_NUM_OF_EXTRACTS + 1]; + uint8_t spec_buf[1024]; + struct rte_flow_attr attr; + const enum rte_flow_action_type *supported = NULL; + uint16_t supported_len = 0; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + const struct rte_flow_action_queue *action_q; + struct dpaa2_queue *rxq = NULL; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + /* check for the valid flow */ + flow = (void *)_flow; + LIST_FOREACH(flow, &priv->flows, next) { + if ((struct rte_flow *)flow == _flow) + goto action_update; + } + DPAA2_PMD_ERR("%s: Flow(%p) is not in %s's flow list", + __func__, flow, dev->data->name); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Invalid flow for action update!"; + err_code = -EINVAL; + + goto quit; + +action_update: + if (flow->fs_flow) { + supported = dpaa2_supported_fs_action_type; + supported_len = RTE_DIM(dpaa2_supported_fs_action_type); + } else { + supported = dpaa2_supported_qos_action_type; + supported_len = RTE_DIM(dpaa2_supported_qos_action_type); + } + if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to verify QoS/FS action!"; + err_code = -ENOTSUP; + goto quit; + } + ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions, fs_actions, + &qos_action_num, &fs_action_num); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to set QoS/FS action!"; + err_code = ret; + goto quit; + } + flow = (struct dpaa2_dev_flow *)_flow; + qos_direct = false; + if (flow->qos_flow && flow->qos_flow->direct_queue) + qos_direct = true; + if (flow->fs_flow && flow->qos_flow && qos_action_num > 0) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM; + err_str = "One-level flow can't update QoS action!"; + err_code = -ENOTSUP; + goto quit; + } + if ((!flow->fs_flow && fs_action_num > 0 && !qos_direct) || + (!flow->qos_flow && qos_action_num > 0)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Flow type and flow action don't match!"; + err_code = -EINVAL; + goto quit; + } + if (fs_action_num > 0 && + dpaa2_flow_action_single_type_check(fs_actions, + RTE_FLOW_ACTION_TYPE_QUEUE)) { + action_q = fs_actions[0].conf; + if (action_q->index >= dev->data->nb_rx_queues) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Queue index is too large!"; + err_code = -EINVAL; + goto quit; + } + rxq = dev->data->rx_queues[action_q->index]; + if (flow->fs_flow && flow->fs_flow->tc_id != rxq->tc_index) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Update queue is not in this TC!"; + err_code = -EINVAL; + goto quit; + } + } + + if (!flow->fs_flow) + goto qos_action_update; + fs_action = &flow->fs_flow->flow_action.fs_action; + if (fs_action->action_type == RTE_FLOW_ACTION_TYPE_RSS) { + is_rss = true; + tc_id = flow->fs_flow->tc_id; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + if (tbl_profile->rss_flow != flow) { + DPAA2_PMD_ERR("%s: RSS flow(%p) != TC[%d]'s rss flow(%p)", + __func__, flow, flow->fs_flow->tc_id, tbl_profile->rss_flow); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "The flow to update is not specified TC's RSS flow!"; + err_code = -EINVAL; + goto quit; + } + } + if (fs_action_num > 0 && + fs_actions[0].type != RTE_FLOW_ACTION_TYPE_PORT_ID && + fs_actions[0].type != RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT && + dpaa2_dev->bus_info->mc_rev >= DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV) { + /** Action HW update doesn't support redirecting frames to other DPNIs.*/ + hw_update = true; + goto skip_remove_fs_entry; + } + + if (!is_rss) { + ret = dpaa2_flow_remove_generic_entry(dev, flow->fs_flow, + DPAA2_FLOW_FS_TYPE); + if (ret) { + DPAA2_PMD_ERR("%s: remove flow fs entry failed(%d)", + __func__, ret); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to remove flow in flow action update!"; + err_code = ret; + + goto quit; + } + } + +skip_remove_fs_entry: + if (is_rss) { + rss_conf = fs_actions[0].conf; + ret = dpaa2_flow_rss_conf_to_item(rss_conf->types, items, + spec_buf, 1024); + if (ret < 0) { + DPAA2_PMD_ERR("TC[%d] converts to RSS items failed(%d)", + flow->fs_flow->tc_id, ret); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to gen rss items in flow action update!"; + err_code = ret; + goto quit; + } else if (!ret) { + DPAA2_PMD_ERR("No item is generated by rss type(0x%" PRIx64 ")", + rss_conf->types); + error_type = RTE_FLOW_ERROR_TYPE_ITEM; + err_str = "No item is generated by rss type!"; + err_code = -ENOTSUP; + goto quit; + } + memset(&attr, 0, sizeof(attr)); + attr.group = flow->fs_flow->tc_id; + attr.ingress = 1; + tbl_profile->tc_cfg.dist_size = rss_conf->queue_num; + memset(&flow->fs_flow->rule_cfg, 0, sizeof(struct dpni_rule_cfg)); + memset(flow->fs_flow->key_addr, 0, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + memset(flow->fs_flow->mask_addr, 0, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + flow->fs_flow->rule_size = 0; + flow->fs_flow->ip_key = NET_PROT_NONE; + flow->fs_flow->ip_src = NET_PROT_NONE; + flow->fs_flow->ip_dst = NET_PROT_NONE; + ret = dpaa2_flow_generic_extract_rule_set(flow->fs_flow, &attr, + items, true, DPAA2_FLOW_FS_TYPE, true); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "RSS action update failed!"; + err_code = ret; + goto quit; + } + } else { + ret = dpaa2_flow_fs_action_update(priv, flow->fs_flow, fs_actions); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "FS action update failed!"; + err_code = ret; + goto quit; + } + if (hw_update) + ret = dpaa2_flow_update_fs_rule_action(priv, flow->fs_flow); + else + ret = dpaa2_flow_add_fs_rule(priv, flow->fs_flow); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "FS rule action update failed!"; + err_code = ret; + goto quit; + } + } +qos_action_update: + if (!flow->qos_flow) + goto quit; + + if (rxq) { + jump_conf.group = rxq->tc_index; + qos_actions[qos_action_num].type = RTE_FLOW_ACTION_TYPE_JUMP; + qos_actions[qos_action_num].conf = &jump_conf; + qos_actions[qos_action_num + 1].type = RTE_FLOW_ACTION_TYPE_END; + } + + hw_update = false; + if (dpaa2_dev->bus_info->mc_rev >= DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV) { + /** Action HW update doesn't support redirecting frames to other DPNIs.*/ + hw_update = true; + goto skip_remove_qos_entry; + } + + ret = dpaa2_flow_remove_generic_entry(dev, flow->qos_flow, + DPAA2_FLOW_QOS_TYPE); + if (ret) { + DPAA2_PMD_ERR("%s: remove flow qos entry failed(%d)", + __func__, ret); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to remove QoS entry in action update!"; + err_code = ret; + + goto quit; + } + +skip_remove_qos_entry: + ret = dpaa2_flow_qos_action_update(priv, flow->qos_flow, qos_actions, + false); + if (ret) { + DPAA2_PMD_ERR("%s: QoS action update failed(%d)", + __func__, ret); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to QoS action update!"; + err_code = ret; + + goto quit; + } + if (rxq) { + flow->qos_flow->direct_queue = true; + flow->qos_flow->flow_id = rxq->flow_id; + } + if (hw_update) + ret = dpaa2_flow_update_qos_rule_action(priv, flow->qos_flow); + else + ret = dpaa2_flow_add_qos_rule(priv, flow->qos_flow); + if (ret) { + DPAA2_PMD_ERR("%s: %s qos flow entry failed(%d)", + __func__, hw_update ? "update" : "add", ret); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update QoS entry action to HW!"; + err_code = ret; + } + +quit: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + return rte_flow_error_set(error, -err_code, error_type, NULL, err_str); +} + /** * Destroy user-configured flow rules. * @@ -5391,24 +5808,113 @@ dpaa2_flow_flush(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_dev_flow *flow = LIST_FIRST(&priv->flows); + int ret = 0; while (flow) { struct dpaa2_dev_flow *next = LIST_NEXT(flow, next); - dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error); + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error); + if (ret) { + DPAA2_PMD_ERR("%s: Remove flow failed(%d)", + __func__, ret); + } + flow = next; } - return 0; + + return ret; } static int -dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, - struct rte_flow *_flow __rte_unused, - const struct rte_flow_action *actions __rte_unused, - void *data __rte_unused, - struct rte_flow_error *error __rte_unused) +dpaa2_flow_query(struct rte_eth_dev *dev, + struct rte_flow *_flow, const struct rte_flow_action *actions, + void *data, struct rte_flow_error *error) { - return 0; + struct dpaa2_dev_flow *flow; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + uint16_t num = 0, num_rsp, i, tc_id = 0; + int ret = 0, found = false; + size_t size, iova; + struct dpni_dump_table_rsp *rsp = NULL; + + RTE_SET_USED(actions); + RTE_SET_USED(data); + RTE_SET_USED(error); + + flow = LIST_FIRST(&priv->flows); + while (flow) { + num++; + if (flow == (struct dpaa2_dev_flow *)_flow) + found = true; + flow = LIST_NEXT(flow, next); + } + if (!num || !found) + return -ENXIO; + num = num * 2;/** Max: FS entry + QoS entry.*/ + flow = (void *)_flow; + size = sizeof(struct dpni_dump_table_header) + + num * sizeof(struct dpni_dump_table_entry); + rsp = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + if (!rsp) + return -ENOMEM; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(rsp, size); + if (iova == RTE_BAD_IOVA) { + DPAA2_PMD_ERR("%s: No IOMMU map for dump table result!", + __func__); + ret = -EIO; + goto quit; + } + + if (priv->num_rx_tc <= 1) + goto dump_fs; + + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_QOS_TABLE, 0/**Any*/, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's QoS table failed(%d)", + dev->data->name, ret); + goto quit; + } + + if (!flow->qos_flow) + goto dump_fs; + + for (i = 0; i < num_rsp; i++) { + if (!memcmp(rsp->entry[i].key, flow->qos_flow->key_addr, + flow->qos_flow->rule_size) && + !memcmp(rsp->entry[i].mask, + flow->qos_flow->mask_addr, flow->qos_flow->rule_size)) + break; + } + +dump_fs: + if (!flow->fs_flow) + goto quit; + + tc_id = flow->fs_flow->tc_id; + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_FS_TABLE, tc_id, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's FS%d table failed(%d)", + dev->data->name, tc_id, ret); + goto quit; + } + for (i = 0; i < num_rsp; i++) { + if (!memcmp(rsp->entry[i].key, flow->fs_flow->key_addr, + flow->fs_flow->rule_size) && + !memcmp(rsp->entry[i].mask, + flow->fs_flow->mask_addr, flow->fs_flow->rule_size)) { + break; + } + } + +quit: + if (rsp) + rte_free(rsp); + + return ret; } /** @@ -5421,19 +5927,44 @@ dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, * Pointer to private structure. */ void -dpaa2_flow_clean(struct rte_eth_dev *dev) +dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id) { - struct dpaa2_dev_flow *flow; + struct dpaa2_dev_flow *flow, *next_flow; struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret; + + flow = LIST_FIRST(&priv->flows); + if (tc_id >= MAX_TCS) + goto clean_all; + while (flow) { + next_flow = LIST_NEXT(flow, next); + if (flow->fs_flow && flow->fs_flow->tc_id == tc_id) { + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + if (ret) { + DPAA2_PMD_ERR("%s: Remove flow failed(%d)", + __func__, ret); + } + } + flow = next_flow; + } + return; - while ((flow = LIST_FIRST(&priv->flows))) - dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); +clean_all: + while (flow) { + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + if (ret) { + DPAA2_PMD_ERR("%s: Remove flow failed(%d)", + __func__, ret); + } + flow = LIST_FIRST(&priv->flows); + } } const struct rte_flow_ops dpaa2_flow_ops = { .create = dpaa2_flow_create, .validate = dpaa2_flow_validate, .destroy = dpaa2_flow_destroy, + .actions_update = dpaa2_flow_actions_update, .flush = dpaa2_flow_flush, .query = dpaa2_flow_query, }; diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4f774f7c82..3f8bee9146 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018-2021 NXP +# Copyright 2018-2026 NXP if not is_linux build = false @@ -8,7 +8,6 @@ endif deps += ['mempool_dpaa2'] sources = files( - 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', 'dpaa2_meter.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 37/47] net/dpaa2: support GENEVE flow item 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (35 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 36/47] net/dpaa2: rework flow engine Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 38/47] net/dpaa2: support flow meter and policer actions Prashant Gupta ` (10 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Add GENEVE flow item support to the dpaa2 flow engine. The GENEVE protocol and VNI fields are matched through the soft parser, so the item is only accepted when the soft parser is loaded. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 102 ++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index e52b796a64..f86e1c0acc 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -140,7 +140,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { static const enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_ECPRI + RTE_FLOW_ITEM_TYPE_ECPRI, + RTE_FLOW_ITEM_TYPE_GENEVE }; static const enum rte_flow_action_type dpaa2_supported_fs_action_type[] = { @@ -248,6 +249,10 @@ static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { .vni = {0xff, 0xff, 0xff}, }; +static const struct rte_flow_item_geneve dpaa2_flow_item_geneve_mask = { + .protocol = RTE_BE16(0xffff), + .vni = {0xff, 0xff, 0xff}, +}; static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { .hdr.common.type = 0xff, @@ -1573,6 +1578,10 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_GENEVE: + mask_support = (const char *)&dpaa2_flow_item_geneve_mask; + size = sizeof(struct rte_flow_item_geneve); + break; default: return -EINVAL; } @@ -3371,6 +3380,89 @@ dpaa2_flow_raw_extract_rule_set(struct dpaa2_generic_flow *flow, return 0; } +static int +dpaa2_flow_geneve_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + int *extract_cfg, enum dpaa2_flow_dist_type dist_type) +{ + int ret, local_cfg = 0; + uint32_t bit_offset; + const struct rte_flow_item_geneve *spec, *mask; + struct dpaa2_dev_priv *priv = flow->priv; + const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + char hex_dump[DPAA2_FLOW_HDR_HEX_DUMP_SIZE]; + + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); + return -ENOTSUP; + } + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_geneve_mask; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-GENEVE distribution not support"); + return -ENOTSUP; + } + + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, + DPAA2_PARSER_GENEVE_ID); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + bit_offset, dist_type, attr->group, &local_cfg); + if (ret) + return ret; + + if (!spec) + goto quit; + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_GENEVE); + if (ret) { + dpaa2_flow_hdr_hexdump(hex_dump, sizeof(hex_dump), (const uint8_t *)mask, + sizeof(struct rte_flow_item_geneve)); + DPAA2_PMD_ERR("Extract GENEVE(%s) failed(%d)", + hex_dump, ret); + + return ret; + } + + if (mask->protocol && mask->protocol != 0xffff) { + DPAA2_PMD_ERR("Not support to extract geneve protocol."); + return -EINVAL; + } + + if (mask->protocol) { + ret = dpaa2_flow_add_pr_extract_rule(flow, + DPAA2_GENEVE_PROTOCOL_OFFSET, + sizeof(mask->protocol), &spec->protocol, + &mask->protocol, priv, attr->group, &local_cfg, + dist_type); + if (ret) + return ret; + } + + if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { + ret = dpaa2_flow_add_pr_extract_rule(flow, + DPAA2_GENEVE_VNI_OFFSET, + sizeof(mask->vni), spec->vni, + mask->vni, + priv, attr->group, &local_cfg, dist_type); + if (ret) + return ret; + } + +quit: + if (extract_cfg) + (*extract_cfg) |= local_cfg; + + return 0; +} static inline int dpaa2_flow_verify_entry(struct dpaa2_dev_priv *priv, @@ -4236,6 +4328,14 @@ dpaa2_flow_generic_extract_rule_set(struct dpaa2_generic_flow *flow, goto end_extract_set; } break; + case RTE_FLOW_ITEM_TYPE_GENEVE: + ret = dpaa2_flow_geneve_extract_rule_set(flow, attr, + &dpaa2_pattern[i], &extract_cfg, dist_type); + if (ret) { + DPAA2_PMD_ERR("GENEVE flow config failed!"); + goto end_extract_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_flow_raw_extract_rule_set(flow, attr, &dpaa2_pattern[i], &extract_cfg, dist_type); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 38/47] net/dpaa2: support flow meter and policer actions 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (36 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 37/47] net/dpaa2: support GENEVE flow item Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 39/47] net/dpaa2: support flow table miss actions Prashant Gupta ` (9 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Add support for the METER and METER_MARK flow actions. A meter flow is programmed per traffic class and configures the DPNI policer from the meter profile and policy that were created through the meter ops. Meter flows carry a single action and are tracked separately from the regular QoS and flow steering entries, so flow create, destroy and action update dispatch them through a dedicated path. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 316 +++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f86e1c0acc..e86e6d1f8b 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -111,6 +111,7 @@ struct dpaa2_dev_flow { struct dpaa2_generic_flow *qos_flow; struct dpaa2_generic_flow *fs_flow; struct dpaa2_dev_priv *priv; + int is_meter_flow; }; struct rte_dpaa2_flow_item { @@ -158,6 +159,10 @@ static const enum rte_flow_action_type dpaa2_supported_qos_action_type[] = { RTE_FLOW_ACTION_TYPE_DROP }; +static const enum rte_flow_action_type dpaa2_supported_meter_action_type[] = { + RTE_FLOW_ACTION_TYPE_METER_MARK, + RTE_FLOW_ACTION_TYPE_METER +}; #define DPAA2_FLOW_HDR_HEX_DUMP_SIZE \ (RTE_MAX(sizeof(struct rte_flow_item_eth), \ @@ -3619,6 +3624,10 @@ dpaa2_flow_verify_fs_action(struct dpaa2_dev_priv *priv, /* Skip this action, have to add for vxlan*/ case RTE_FLOW_ACTION_TYPE_DROP: break; + case RTE_FLOW_ACTION_TYPE_METER_MARK: + break; + case RTE_FLOW_ACTION_TYPE_METER: + break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; break; @@ -4062,7 +4071,146 @@ dpaa2_flow_table_update(struct dpaa2_dev_priv *priv, return 0; } +static int +dpaa2_flow_action_meter_mark_init(struct dpaa2_dev_priv *priv, + uint32_t mtr_id, struct rte_flow_action_meter_mark *meter_mark) +{ + struct dpaa2_dev_meter *meter; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + int found = 0; + + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->meter_id == mtr_id) { + found = 1; + break; + } + meter = LIST_NEXT(meter, next); + } + + if (!found) { + DPAA2_PMD_ERR("Meter ID(%d) is not found!", mtr_id); + return -ENXIO; + } + + found = 0; + profile = LIST_FIRST(&priv->profiles); + while (profile) { + if (profile->profile_id == meter->profile_id) { + found = 1; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + DPAA2_PMD_ERR("Meter ID(%d)'s profile(%d) not exist!", + mtr_id, meter->profile_id); + return -ENXIO; + } + + found = 0; + policy = LIST_FIRST(&priv->policies); + while (policy) { + if (policy->policy_id == meter->policy_id) { + found = 1; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + /** Option.*/ + DPAA2_PMD_WARN("Meter ID(%d)'s policy(%d) not exist!", + mtr_id, meter->policy_id); + policy = NULL; + } + meter_mark->profile = (void *)profile; + meter_mark->policy = (void *)policy; + meter_mark->color_mode = 1; + + return 0; +} + +static int +dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, + uint8_t tc_id, const struct rte_flow_action_meter_mark *meter_mark) +{ + struct rte_dpaa2_device *dpaa2_dev; + struct dpni_rx_tc_policing_cfg policing_cfg = {0}; + const struct dpaa2_dev_meter_profile *dpaa2_profile; + const struct dpaa2_dev_meter_policy *dpaa2_policy = NULL; + int ret; + + if (!(priv->options & DPNI_OPT_HAS_POLICING)) { + DPAA2_PMD_ERR("POLICING(0x%08x) was not added in DPNI creating options(0x%08x)", + DPNI_OPT_HAS_POLICING, priv->options); + return -ENOTSUP; + } + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + + dpaa2_profile = (void *)meter_mark->profile; + if (!dpaa2_profile) { + DPAA2_PMD_ERR("Meter profile not specified!"); + return -EINVAL; + } + + /** Blind as default.*/ + policing_cfg.options = 0; + if (meter_mark->color_mode) + policing_cfg.options = DPNI_POLICER_OPT_COLOR_AWARE; + if (meter_mark->policy) + dpaa2_policy = (void *)meter_mark->policy; + if (dpaa2_policy && dpaa2_policy->red_drop) { + policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + } else if (!dpaa2_policy) { + /** Default: Red is discarded if no policy specified.*/ + policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + } + + if (priv->flow_profile.mtr_flow[tc_id]) { + /** Update existing policer.*/ + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + policing_cfg.options |= DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS; + if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV) + DPAA2_PMD_WARN("The existing policer's counters will be cleaned."); + } + + policing_cfg.mode = dpaa2_profile->mode; + if (policing_cfg.mode < DPNI_POLICER_MODE_NONE || + policing_cfg.mode > DPNI_POLICER_MODE_RFC_4115) { + DPAA2_PMD_ERR("Invalid policer mode(%d)", + policing_cfg.mode); + return -EINVAL; + } + policing_cfg.units = dpaa2_profile->policer_unit; + if (policing_cfg.units < DPNI_POLICER_UNIT_BYTES_L3 || + policing_cfg.units > DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS) { + DPAA2_PMD_ERR("Invalid policer units(%d)", + policing_cfg.units); + return -EINVAL; + } + policing_cfg.cir = dpaa2_profile->cir; + policing_cfg.cbs = dpaa2_profile->cbs; + policing_cfg.eir = dpaa2_profile->pir; + policing_cfg.ebs = dpaa2_profile->pbs; + + if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &policing_cfg); + } else { + ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &policing_cfg); + } + DPAA2_PMD_INFO("%s RX TC%d policer configure %s.", + priv->eth_dev->data->name, tc_id, + ret ? "failed" : "successfully"); + if (!ret) + priv->flow_profile.tc_mtr_profile[tc_id] = (void *)meter_mark->profile; + + return ret; +} static int dpaa2_flow_action_single_type_check(const struct rte_flow_action actions[], @@ -4119,6 +4267,8 @@ dpaa2_flow_fs_action_update(struct dpaa2_dev_priv *priv, const struct rte_flow_action actions[]) { int end_of_list = 0, ret = 0, i = 0; + const struct rte_flow_action_meter *meter; + struct rte_flow_action_meter_mark meter_mark; union dpaa2_dev_flow_action flow_action_rollback; rte_memcpy(&flow_action_rollback, &fs_flow->flow_action, @@ -4136,6 +4286,26 @@ dpaa2_flow_fs_action_update(struct dpaa2_dev_priv *priv, if (ret) goto end_action_set; + break; + case RTE_FLOW_ACTION_TYPE_METER_MARK: + rte_memcpy(&meter_mark, actions[i].conf, + sizeof(meter_mark)); + ret = dpaa2_flow_set_police_action(priv, + fs_flow->tc_id, &meter_mark); + if (ret) + goto end_action_set; + break; + case RTE_FLOW_ACTION_TYPE_METER: + meter = actions[i].conf; + ret = dpaa2_flow_action_meter_mark_init(priv, + meter->mtr_id, &meter_mark); + if (ret) + goto end_action_set; + ret = dpaa2_flow_set_police_action(priv, + fs_flow->tc_id, &meter_mark); + if (ret) + goto end_action_set; + break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan*/ @@ -4557,6 +4727,29 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, } } + supported = dpaa2_supported_meter_action_type; + supported_len = RTE_DIM(dpaa2_supported_meter_action_type); + if (dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + DPAA2_PMD_DEBUG("This is meter flow."); + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + err_str = "Meter flow's type can't be QoS flow."; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION; + ret = -EPERM; + goto invalid_params; + } + if (actions[1].type != RTE_FLOW_ACTION_TYPE_END) { + err_str = "Meter flow can't support multi-actions."; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM; + ret = -EPERM; + goto invalid_params; + } + if (pattern) + DPAA2_PMD_WARN("Meter flow ingores flow items!"); + return 0; + } + /* Verify input action list */ if (group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW || group_type == RTE_DPAA2_FS_GROUP_FLOW) { @@ -5383,6 +5576,51 @@ dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev, return NULL; } +static struct rte_flow * +dpaa2_flow_create_meter_flow(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_action meter_action[]) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *flow = NULL; + struct dpaa2_generic_flow *fs_flow = NULL; + int ret; + + if (attr->group >= priv->num_rx_tc) + return NULL; + + if (priv->flow_profile.mtr_flow[attr->group]) + return NULL; + + fs_flow = rte_zmalloc(NULL, sizeof(struct dpaa2_generic_flow), + RTE_CACHE_LINE_SIZE); + if (!fs_flow) { + DPAA2_PMD_ERR("Failure to allocate memory for flow"); + return NULL; + } + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + rte_free(fs_flow); + DPAA2_PMD_ERR("Failure to allocate memory for flow"); + return NULL; + } + fs_flow->tc_id = attr->group; + fs_flow->priv = priv; + flow->fs_flow = fs_flow; + flow->priv = priv; + + ret = dpaa2_flow_fs_action_update(priv, fs_flow, meter_action); + if (ret) { + rte_free(fs_flow); + rte_free(flow); + return NULL; + } + flow->is_meter_flow = true; + priv->flow_profile.mtr_flow[fs_flow->tc_id] = flow; + + return (struct rte_flow *)flow; +} static struct rte_flow * dpaa2_flow_create(struct rte_eth_dev *dev, @@ -5447,6 +5685,30 @@ dpaa2_flow_create(struct rte_eth_dev *dev, rss_item = true; } + if (dpaa2_flow_check_actions_support(actions, + dpaa2_supported_meter_action_type, + RTE_DIM(dpaa2_supported_meter_action_type))) { + /** Assume it's meter flow per TC.*/ + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) { + error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP; + err_code = -EINVAL; + err_str = "Failed to converts RSS config type to RSS items!"; + goto flow_failure; + } + if (actions[1].type != RTE_FLOW_ACTION_TYPE_END) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM; + err_code = -EPERM; + err_str = "Meter flow can't support multi-actions."; + goto flow_failure; + } + flow = (void *)dpaa2_flow_create_meter_flow(dev, &local_attr, actions); + if (flow) + return (struct rte_flow *)flow; + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Failed to create meter flow!"; + goto flow_failure; + } DPAA2_PMD_DEBUG("Port %s-%s: group type:%d, group id:%d, total RX TCs:%d", dev->data->name, __func__, group_type, group_id, priv->num_rx_tc); @@ -5573,6 +5835,38 @@ dpaa2_flow_create(struct rte_eth_dev *dev, return NULL; } +static int +dpaa2_flow_destroy_meter_flow(struct rte_eth_dev *dev, + struct dpaa2_dev_flow *flow) +{ + struct rte_dpaa2_device *dpaa2_dev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + uint8_t tc_id; + + RTE_ASSERT(!flow->qos_flow && flow->fs_flow); + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + tc_id = flow->fs_flow->tc_id; + RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow); + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = DPNI_POLICER_MODE_NONE; + if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &cfg); + } else { + ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &cfg); + } + if (ret) + return ret; + priv->flow_profile.tc_mtr_profile[tc_id] = NULL; + priv->flow_profile.mtr_flow[tc_id] = NULL; + rte_free(flow->fs_flow); + rte_free(flow); + + return 0; +} static int dpaa2_flow_destroy(struct rte_eth_dev *dev, @@ -5587,6 +5881,8 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, RTE_SET_USED(error); flow = (struct dpaa2_dev_flow *)_flow; + if (flow->is_meter_flow) + return dpaa2_flow_destroy_meter_flow(dev, flow); LIST_REMOVE(flow, next); @@ -5663,6 +5959,26 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, /* check for the valid flow */ flow = (void *)_flow; + if (flow->is_meter_flow) { + RTE_ASSERT(flow->fs_flow); + tc_id = flow->fs_flow->tc_id; + RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow); + supported = dpaa2_supported_meter_action_type; + supported_len = RTE_DIM(dpaa2_supported_meter_action_type); + if (!dpaa2_flow_check_actions_support(actions, supported, supported_len)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to verify meter action!"; + err_code = -ENOTSUP; + goto quit; + } + ret = dpaa2_flow_fs_action_update(priv, flow->fs_flow, actions); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update meter action!"; + err_code = ret; + } + goto quit; + } LIST_FOREACH(flow, &priv->flows, next) { if ((struct rte_flow *)flow == _flow) goto action_update; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 39/47] net/dpaa2: support flow table miss actions 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (37 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 38/47] net/dpaa2: support flow meter and policer actions Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 40/47] net/dpaa2: support Rx mempool per traffic class Prashant Gupta ` (8 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Implement the group_set_miss_actions callback so that the default action of the QoS and flow steering tables can be configured. A table miss either drops the frame, steers it to a default queue, or jumps to a default traffic class. The default action is applied while the port is configured, so that the tables have a defined miss behaviour before any flow rule is added. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 58 ++++++++ drivers/net/dpaa2/dpaa2_flow.c | 237 +++++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 32fab43142..812e3f529f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -354,6 +354,52 @@ static int dpaa2_dev_link_update(struct rte_eth_dev *dev, static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev); static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev); static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); +static int +dpaa2_setup_table_miss_action(struct rte_eth_dev *eth_dev, + uint8_t tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct rte_flow_group_attr attr; + struct rte_flow_action actions[2]; + struct dpaa2_flow_tbl_profile *tbl_profile; + + memset(&attr, 0, sizeof(attr)); + attr.ingress = 1; + if (tc_index < priv->num_rx_tc) { + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (tbl_profile->default_drop) { + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else if (tbl_profile->default_queue.index >= eth_dev->data->nb_rx_queues) { + DPAA2_PMD_DEBUG("%s-tc%d-default-rxq(%d) >= max rxq(%d), Force to drop.", + eth_dev->data->name, tc_index, tbl_profile->default_queue.index, + eth_dev->data->nb_rx_queues); + tbl_profile->default_drop = true; + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else { + actions[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; + actions[0].conf = &tbl_profile->default_queue; + } + } else { + tbl_profile = &priv->flow_profile.qos_profile; + if (tbl_profile->default_drop) { + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else if (tbl_profile->default_jump.group >= priv->num_rx_tc) { + DPAA2_PMD_DEBUG("%s-default-tc(%d) >= max tc(%d), Force to drop.", + eth_dev->data->name, tbl_profile->default_jump.group, + priv->num_rx_tc); + tbl_profile->default_drop = true; + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else { + actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + actions[0].conf = &tbl_profile->default_jump; + } + } + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + + return rte_flow_group_set_miss_actions(eth_dev->data->port_id, + tc_index, &attr, actions, NULL); +} + static int dpaa2_setup_flow_rss_dist(struct rte_eth_dev *eth_dev, uint64_t req_dist_set, int tc_index) @@ -1087,6 +1133,13 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) def_act_conf->default_flows[tc_index]; } } + if (priv->fs_entries) { + ret = dpaa2_setup_table_miss_action(dev, tc_index); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-tc%d table", + ret, dev->data->name, tc_index); + } + } } if (def_act_conf) { tbl_profile = &priv->flow_profile.qos_profile; @@ -1097,6 +1150,11 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) tbl_profile->default_jump.group = def_act_conf->default_tc; } } + ret = dpaa2_setup_table_miss_action(dev, priv->num_rx_tc); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-QoS table", + ret, dev->data->name); + } if (eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index e86e6d1f8b..a51225d38d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -3831,6 +3831,52 @@ dpaa2_flow_clear_fs_table(struct dpaa2_dev_priv *priv, return 0; } +static int +dpaa2_flow_fs_table_set_default(struct dpaa2_dev_priv *priv, + uint8_t tc_id, int discard, uint16_t default_queue) +{ + int ret; + struct rte_dpaa2_device *dpaa2_dev; + struct dpni_rx_dist_cfg *tc_cfg; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_queue *queue; + char mc_rev[1024]; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", + RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + if (!tbl_profile->dpkg.num_extracts && + dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + DPAA2_PMD_DEBUG("%s can't set miss action of FS table indepentently.", + mc_rev); + return 0; + } + tc_cfg = &tbl_profile->tc_cfg; + tc_cfg->enable = true; + if (discard) { + tbl_profile->default_drop = true; + tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP; + } else { + queue = dpaa2_flow_queue_action_to_queue(priv, tc_id, default_queue); + if (!queue) + return -EINVAL; + tbl_profile->default_drop = false; + tbl_profile->default_queue.index = default_queue; + tc_cfg->fs_miss_flow_id = queue->flow_id; + } + ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("%s: Failed(%d) to set default action of TC[%d]", + __func__, ret, tc_id); + return ret; + } + + return 0; +} static int dpaa2_flow_fs_rss_table_config(struct dpaa2_dev_priv *priv, @@ -3924,6 +3970,62 @@ dpaa2_flow_fs_rss_table_config(struct dpaa2_dev_priv *priv, return 0; } +static int +dpaa2_flow_qos_table_set_default(struct dpaa2_dev_priv *priv, + int discard, uint8_t default_tc, uint16_t default_flow) +{ + int ret; + struct rte_dpaa2_device *dpaa2_dev; + struct dpni_qos_tbl_cfg qos_cfg; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + char mc_rev[1024]; + + dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); + tbl_profile = &priv->flow_profile.qos_profile; + snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", + RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), + RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + if (!tbl_profile->dpkg.num_extracts && + dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + DPAA2_PMD_DEBUG("%s can't set miss action of QoS table indepentently.", + mc_rev); + return 0; + } + if (default_flow < priv->dist_queues && + dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) { + DPAA2_PMD_WARN("%s can't direct miss traffic to TC%d-flow%d by QoS table only.", + mc_rev, default_tc, default_flow); + return 0; + } + + rte_memcpy(&qos_cfg, &tbl_profile->qos_cfg, sizeof(struct dpni_qos_tbl_cfg)); + qos_cfg.key_cfg_iova = 0; + qos_cfg.default_tc = default_tc; + qos_cfg.default_flow_id = default_flow; + qos_cfg.discard_on_miss = discard ? true : false; + qos_cfg.set_default_flow_id = default_flow < priv->dist_queues ? true : false; + + ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, &qos_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("%s: Failed(%d) to set default action of QoS", + __func__, ret); + return ret; + } + if (discard) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_jump.group = default_tc; + } + rte_memcpy(&tbl_profile->qos_cfg.discard_on_miss, + &qos_cfg.discard_on_miss, + sizeof(struct dpni_qos_tbl_cfg) - + offsetof(struct dpni_qos_tbl_cfg, discard_on_miss)); + + return 0; +} static int dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, @@ -5927,6 +6029,140 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, return qos_ret ? qos_ret : fs_ret; } +static int +dpaa2_flow_set_miss_actions(struct rte_eth_dev *dev, + uint32_t group, const struct rte_flow_group_attr *attr, + const struct rte_flow_action actions[], struct rte_flow_error *err) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + enum dpaa2_flow_dist_type flow_type = DPAA2_FLOW_NULL_TYPE; + int end_of_list = 0, i = 0, discard = false, err_code = 0; + const struct rte_flow_action_jump *action_jump = NULL; + const struct rte_flow_action_queue *dest_queue = NULL; + uint32_t group_id, group_type; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + struct dpaa2_queue *miss_rxq = NULL; + uint8_t qos_tc = 0xff; + uint16_t qos_flow = 0xffff; + + RTE_SET_USED(attr); + + group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(group); + if (group_id >= priv->num_rx_tc && + group_type == RTE_DPAA2_ONE_LEVEL_GROUP_FLOW) { + group_type = RTE_DPAA2_QOS_GROUP_FLOW; + group_id = 0; + } + if (group_type == RTE_DPAA2_QOS_GROUP_FLOW) + flow_type = DPAA2_FLOW_QOS_TYPE; + else if (group_type == RTE_DPAA2_FS_GROUP_FLOW) + flow_type = DPAA2_FLOW_FS_TYPE; + else if (group >= priv->num_rx_tc) + flow_type = DPAA2_FLOW_QOS_TYPE; + else + flow_type = DPAA2_FLOW_FS_TYPE; + + while (!end_of_list) { + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + dest_queue = actions[i].conf; + if (dest_queue->index >= dev->data->nb_rx_queues) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION_CONF; + err_code = -EINVAL; + err_str = "Queue index overflows"; + goto failure_to_set_miss_actions; + } + miss_rxq = priv->rx_vq[dest_queue->index]; + break; + case RTE_FLOW_ACTION_TYPE_JUMP: + action_jump = actions[i].conf; + break; + case RTE_FLOW_ACTION_TYPE_DROP: + discard = true; + break; + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_WARN("Invalid default action type[%d]:(%d)", + i, actions[i].type); + break; + } + i++; + } + + if (flow_type == DPAA2_FLOW_QOS_TYPE) { + if (!priv->qos_entries) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "No QoS table available!"; + goto failure_to_set_miss_actions; + } + if (action_jump && miss_rxq) { + if (action_jump->group != miss_rxq->tc_index) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Jump group conflicts to miss queue's TC"; + goto failure_to_set_miss_actions; + } + } + if (action_jump) + qos_tc = action_jump->group; + if (miss_rxq) { + qos_tc = miss_rxq->tc_index; + qos_flow = miss_rxq->flow_id; + } + if ((!discard && qos_tc == 0xff) || + (discard && qos_tc != 0xff)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Invalid miss action set for QoS table"; + goto failure_to_set_miss_actions; + } + err_code = dpaa2_flow_qos_table_set_default(priv, discard, qos_tc, qos_flow); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to set miss action for QoS table"; + goto failure_to_set_miss_actions; + } + + return 0; + } + + if (!priv->fs_entries) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "No FS table available!"; + goto failure_to_set_miss_actions; + } + if (!discard && !miss_rxq) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Invalid miss action set for FS table"; + goto failure_to_set_miss_actions; + } + if (miss_rxq && miss_rxq->tc_index != group_id) { + error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP; + err_code = -EINVAL; + err_str = "Group conflicts with dest queue's TC ID"; + goto failure_to_set_miss_actions; + } + err_code = dpaa2_flow_fs_table_set_default(priv, group_id, discard, + dest_queue ? dest_queue->index : 0); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to set miss action for FS table"; + } + +failure_to_set_miss_actions: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(err, -err_code, error_type, NULL, err_str); + + return err_code; +} static int dpaa2_flow_actions_update(struct rte_eth_dev *dev, @@ -6380,6 +6616,7 @@ const struct rte_flow_ops dpaa2_flow_ops = { .create = dpaa2_flow_create, .validate = dpaa2_flow_validate, .destroy = dpaa2_flow_destroy, + .group_set_miss_actions = dpaa2_flow_set_miss_actions, .actions_update = dpaa2_flow_actions_update, .flush = dpaa2_flow_flush, .query = dpaa2_flow_query, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 40/47] net/dpaa2: support Rx mempool per traffic class 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (38 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 39/47] net/dpaa2: support flow table miss actions Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 41/47] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta ` (7 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Support configuring RX mempool per TC. This patch isolates mempools by traffic class to avoid individual TC's performance being impacted by lack of memory. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 119 ++++++++++++++++++++++++++++++- drivers/net/dpaa2/dpaa2_ethdev.h | 2 +- 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 812e3f529f..e44c073f82 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -546,6 +546,101 @@ dpaa2_update_flow_rss_dist(struct rte_eth_dev *eth_dev, return ret; } +static int +dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, + struct fsl_mc_io *dpni, void *blist, uint8_t tc_id) +{ + /* Function to attach a DPNI with a buffer pool list. Buffer pool list + * handle is passed in blist. + */ + int32_t retcode; + struct dpni_pools_cfg *bpool_cfg = &priv->pools_cfg; + struct dpaa2_bp_list *bp_list = blist; + struct dpni_buffer_layout layout; + int tot_size, out_min_hdr_room, in_min_hdr_room; + uint8_t bp_idx; + struct rte_mempool *mp = bp_list->mp; + + if (priv->flow_profile.mempool[tc_id] != mp) { + if (!priv->flow_profile.mempool[tc_id]) { + bp_idx = bpool_cfg->num_dpbp; + bpool_cfg->num_dpbp++; + priv->flow_profile.bp_idx[tc_id] = bp_idx; + } else { + bp_idx = priv->flow_profile.bp_idx[tc_id]; + } + priv->flow_profile.mempool[tc_id] = mp; + } else { + bp_idx = priv->flow_profile.bp_idx[tc_id]; + } + + /* ... rx buffer layout . + * Check alignment for buffer layouts first + */ + + /* ... rx buffer layout ... */ + if (priv->tx_conf_type == DPAA2_TX_DYNAMIC_CONF) { + /** Additional headroom layout for IPSec with TX configure + * dynamic enabled. + */ + in_min_hdr_room = DPAA2_RX_MIN_FD_OFFSET + + DPAA2_SEC_SIMPLE_FD_IB_MIN; + out_min_hdr_room = DPAA2_DYN_TX_MIN_FD_OFFSET + + DPAA2_SEC_SIMPLE_FD_OB_MIN; + tot_size = RTE_MAX(in_min_hdr_room, out_min_hdr_room); + if (tot_size < RTE_PKTMBUF_HEADROOM) + tot_size = RTE_PKTMBUF_HEADROOM; + } else { + tot_size = RTE_PKTMBUF_HEADROOM; + } + tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN); + + memset(&layout, 0, sizeof(struct dpni_buffer_layout)); + layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | + DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | + DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | + DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | + DPNI_BUF_LAYOUT_OPT_TIMESTAMP | + DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; + + layout.pass_timestamp = true; + layout.pass_frame_status = 1; + layout.private_data_size = DPAA2_FD_PTA_SIZE; + layout.pass_parser_result = 1; + layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN; + layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - + DPAA2_MBUF_HW_ANNOTATION; + retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token, + DPNI_QUEUE_RX, &layout); + if (retcode) { + DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)", + retcode); + return retcode; + } + + /*Attach buffer pool to the network interface as described by the user*/ + bpool_cfg->pools[bp_idx].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; + bpool_cfg->pools[bp_idx].backup_pool = 0; + bpool_cfg->pools[bp_idx].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size, + DPAA2_PACKET_LAYOUT_ALIGN); + /* priority_mask is a bitmask of the traffic classes served by this + * buffer pool, not a traffic class index. MC treats a zero mask as + * 0xff (all traffic classes). + */ + bpool_cfg->pools[bp_idx].priority_mask = RTE_BIT32(tc_id); + + retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, bpool_cfg); + if (retcode) { + DPAA2_PMD_ERR("Error(%d) configuring pools[%d](id=%d) on %s.", + retcode, bp_idx, bpool_cfg->pools[bp_idx].dpbp_id, + priv->eth_dev->data->name); + return retcode; + } + + priv->bp_list = bp_list; + return 0; +} + static int dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { @@ -1321,7 +1416,8 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, struct dpni_taildrop taildrop; uint8_t qopt = 0; uint16_t flow_id; - int ret; + uint32_t bpid; + int ret, ops_idx; PMD_INIT_FUNC_TRACE(); @@ -1346,6 +1442,27 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } + + ops_idx = rte_dpaa2_mpool_get_ops_idx(); + if (ops_idx != mb_pool->ops_index) { + DPAA2_PMD_ERR("MP(%s)'s ops index(%d) != %d", + mb_pool->name, mb_pool->ops_index, ops_idx); + return -EINVAL; + } + + if (!priv->bp_list || priv->bp_list->mp != mb_pool) { + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + ret = rte_dpaa2_bpid_info_init(mb_pool); + if (ret) + return ret; + } + bpid = mempool_to_bpid(mb_pool); + ret = dpaa2_attach_bp_list(priv, dpni, + rte_dpaa2_bpid_info[bpid].bp_list, + dpaa2_q->tc_index); + if (ret) + return ret; + } cfg = rte_zmalloc(NULL, sizeof(struct dpni_queue), 0); if (!cfg) return -ENOMEM; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 312738931f..0934e04198 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -405,7 +405,7 @@ struct dpaa2_dev_priv { /** RXQs in same TC share same cgid.*/ uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; - + struct dpni_pools_cfg pools_cfg; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. * Zero means "use default" (= nb_rx_queues clamped to dist_queues). -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 41/47] drivers: consume dpaa2 DQRR entries in batches 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (39 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 40/47] net/dpaa2: support Rx mempool per traffic class Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 42/47] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta ` (6 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Hemant Agrawal <hemant.agrawal@nxp.com> Each DQRR entry consumed by the software portal costs a write to the cache-invalidate DCAP register. The DCAP register also supports a vector mode where a bitmap of DQRR indices is consumed with a single write, so accumulate the indices and flush the vector once half the ring is pending. A smaller threshold gives little benefit, and a threshold close to the ring size starves WRIOP of DQRR space. Because entries are now released in batches, a caller that stops polling a portal must flush the pending vector explicitly. Pass a NULL dequeue result to qbman_swp_dqrr_consume() to do that when the eventdev dequeue finds the portal dry, when the net PMD finishes draining a portal, and when a portal is released back to the bus. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 4 ++ .../fslmc/qbman/include/fsl_qbman_portal.h | 5 +- drivers/bus/fslmc/qbman/qbman_portal.c | 68 +++++++++++++++++-- drivers/bus/fslmc/qbman/qbman_portal.h | 11 ++- drivers/event/dpaa2/dpaa2_eventdev.c | 4 ++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 + 6 files changed, 86 insertions(+), 8 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 20d1bb2a66..cfd9548fb0 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -305,6 +305,10 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) { if (dpio_dev) { + /* consume indices may still be pending in the portal's DQRR + * consume vector; flush them before the portal is released. + */ + qbman_swp_dqrr_consume(dpio_dev->sw_portal, NULL); /* rx-queue interrupts (net PMD) can arm a portal without the * event driver; tear it down unconditionally. Safe when never * armed: intr_deinit returns early if intr is not enabled. diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index b9e7789766..73e57bcdc1 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -451,7 +451,10 @@ void qbman_swp_prefetch_dqrr_next(struct qbman_swp *s); * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from * qbman_swp_dqrr_next(). * @s: the software portal object. - * @dq: the DQRR entry to be consumed. + * @dq: the DQRR entry to be consumed, NULL to consume the entries accumulated + * so far. Entries are accumulated and consumed in batches, so a caller which + * stops polling the portal must call this with a NULL dq to release the + * entries it has already processed. */ __rte_internal void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq); diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index c93bec5dd3..64b61a5551 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020,2023-2024 NXP + * Copyright 2018-2020,2023-2024,2026 NXP * */ @@ -9,13 +9,20 @@ #include "qbman_portal.h" #include <eal_export.h> +#include <rte_bitops.h> /* QBMan portal management command codes */ #define QBMAN_MC_ACQUIRE 0x30 #define QBMAN_WQCHAN_CONFIGURE 0x46 /* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ -#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6) +#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) + +/* DCAP consume-index-vector mode: the vector of DQRR indices to consume starts + * at bit 16 of DCAP and bit 8 selects vector mode over single-index mode. + */ +#define DQRR_DCAP_CI_VEC_OFFSET 16 +#define DQRR_DCAP_CI_VEC_SELECT 0x100 /* QBMan FQ management command codes */ #define QBMAN_FQ_SCHEDULE 0x48 @@ -284,6 +291,18 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) p->dqrr.dqrr_size = 8; p->dqrr.reset_bug = 0; } + /* Consume DQRR entries in vector mode by default and flush the vector + * once half the ring is pending. A smaller threshold gives little + * benefit; a threshold close to the ring size starves WRIOP of DQRR + * space and slows its enqueues down. + * + * The DCAP consume vector only holds (32 - DQRR_DCAP_CI_VEC_OFFSET) + * index bits, so vector mode can only address a ring that fits in + * them; fall back to per-entry consume for anything larger. + */ + p->dqrr.ci_vec_en = + p->dqrr.dqrr_size <= (32 - DQRR_DCAP_CI_VEC_OFFSET); + p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { @@ -2225,13 +2244,47 @@ const struct qbman_result *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s) return p; } -/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ +/* Write the pending consume vector to DCAP if it holds at least "threshold" + * indices, consuming all of them with a single register access. + */ +static inline void +qbman_swp_dqrr_vec_flush(struct qbman_swp *s, uint8_t threshold) +{ + if (s->dqrr.ci_count < threshold) + return; + + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + s->dqrr.ci_vector | DQRR_DCAP_CI_VEC_SELECT); + s->dqrr.ci_vector = 0; + s->dqrr.ci_count = 0; +} + +/* Add a DQRR index to the pending consume vector, flushing it once the + * configured threshold is reached. + */ +static inline void +qbman_swp_dqrr_vec_consume(struct qbman_swp *s, uint8_t idx) +{ + s->dqrr.ci_vector |= RTE_BIT32(idx + DQRR_DCAP_CI_VEC_OFFSET); + s->dqrr.ci_count++; + qbman_swp_dqrr_vec_flush(s, s->dqrr.ci_flush_th); +} + +/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). + * A NULL dq flushes any indices still pending in the consume vector, which + * the caller must do before it stops polling the portal. + */ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_consume) void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq) { - qbman_cinh_write(&s->sys, - QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); + if (unlikely(dq == NULL)) + qbman_swp_dqrr_vec_flush(s, 1); + else if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, QBMAN_IDX_FROM_DQRR(dq)); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + QBMAN_IDX_FROM_DQRR(dq)); } /* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ @@ -2239,7 +2292,10 @@ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_idx_consume) void qbman_swp_dqrr_idx_consume(struct qbman_swp *s, uint8_t dqrr_index) { - qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); + if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, dqrr_index); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); } /*********************************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.h b/drivers/bus/fslmc/qbman/qbman_portal.h index 1cf7918309..db74db5fe1 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.h +++ b/drivers/bus/fslmc/qbman/qbman_portal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020 NXP + * Copyright 2018-2020, 2026 NXP * */ @@ -93,6 +93,15 @@ struct qbman_swp { uint32_t valid_bit; uint8_t dqrr_size; int reset_bug; + /* Consume index vector: instead of writing DCAP once per + * consumed entry, the indices are accumulated in ci_vector + * and written with a single DCAP access once ci_count + * reaches ci_flush_th. + */ + bool ci_vec_en; + uint8_t ci_count; + uint8_t ci_flush_th; + uint32_t ci_vector; } dqrr; struct { uint32_t pi; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 95d9154b11..5d32bd9fd6 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -320,6 +320,10 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], do { dq = qbman_swp_dqrr_next(swp); if (!dq) { + /* portal is dry: consume whatever is still pending in + * the DQRR consume vector before leaving it idle. + */ + qbman_swp_dqrr_consume(swp, NULL); if (!num_pkts && timeout_ticks) { dpaa2_eventdev_dequeue_wait(timeout_ticks); timeout_ticks = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index e44c073f82..27ddb106c8 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3518,6 +3518,8 @@ dpaa2_napi_drain_portal(struct dpaa2_dpio_dev *dpio) while ((dq = qbman_swp_dqrr_next(dpio->sw_portal))) qbman_swp_dqrr_consume(dpio->sw_portal, dq); + /* flush the indices still pending in the DQRR consume vector */ + qbman_swp_dqrr_consume(dpio->sw_portal, NULL); qbman_swp_interrupt_clear_status(dpio->sw_portal, 0xffffffff); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 42/47] drivers: resolve dpaa2 endpoint in the net driver 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (40 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 41/47] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 43/47] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta ` (5 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Hemant Agrawal <hemant.agrawal@nxp.com> The DPRC object driver walked every device on the bus and, for each DPNI, issued dprc_get_connection() to find the object it is wired to. Two things are wrong with that. The bus keeps the result in struct rte_dpaa2_device even though only the net driver consumes it, and a failure to resolve one DPNI's endpoint aborted the creation of the whole container. The endpoint name was also formatted from endpoint2 outside the DPNI branch, so non-DPNI devices got a name built from uninitialised or stale data. Move the lookup to dpaa2_dev_init(), which already knows it is dealing with a DPNI and can fail the probe of that one port. This also fills in priv->ep_dev_type, priv->ep_object_id and priv->ep_name, which the net driver reads for MAC-level operations, recycle/loopback configuration and rte_pmd_dpaa2_ep_name(), but which nothing assigned. dpsw endpoints are now recognised, and dpdmux/dpsw names carry the interface index because those endpoints are per-interface. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 3 -- drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 45 +++--------------- drivers/net/dpaa2/dpaa2_ethdev.c | 58 +++++++++++++++++++++++- drivers/net/dpaa2/dpaa2_recycle.c | 15 +++--- 4 files changed, 70 insertions(+), 51 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 3ba865e632..6647eeac8f 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -104,10 +104,7 @@ struct rte_dpaa2_device { struct rte_device device; /**< Inherit core device */ enum rte_dpaa2_dev_type dev_type; /**< Device Type */ uint16_t object_id; /**< DPAA2 Object ID */ - enum rte_dpaa2_dev_type ep_dev_type; /**< Endpoint Device Type */ struct dpaa2_dprc_dev *container; - uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */ - char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ const struct rte_fslmc_bus_info *bus_info; diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c index 868ed646af..6441297ecf 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c @@ -27,7 +27,6 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, struct rte_dpaa2_device *obj) { struct dpaa2_dprc_dev *dprc_node; - struct dprc_endpoint endpoint1, endpoint2; struct rte_dpaa2_device *dev; int ret, dprc_id = obj->object_id; @@ -49,45 +48,13 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, return ret; } - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - /** DPRC is always created before it's children are created.*/ + /* DPRC is always created before its children are created, so every + * device scanned so far belongs to this container. Endpoint lookup is + * left to the object drivers, which know how many interfaces their + * object has and can report a failure to their own caller. + */ + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) dev->container = dprc_node; - if (dev->dev_type == DPAA2_ETH) { - int link_state; - - memset(&endpoint1, 0, sizeof(struct dprc_endpoint)); - memset(&endpoint2, 0, sizeof(struct dprc_endpoint)); - strcpy(endpoint1.type, "dpni"); - endpoint1.id = dev->object_id; - ret = dprc_get_connection(&dprc_node->dprc, - CMD_PRI_LOW, - dprc_node->token, - &endpoint1, &endpoint2, - &link_state); - if (ret) { - DPAA2_BUS_ERR("dpni.%d connection failed!", - dev->object_id); - dprc_close(&dprc_node->dprc, CMD_PRI_LOW, - dprc_node->token); - rte_free(dprc_node); - return ret; - } - - if (!strcmp(endpoint2.type, "dpmac")) - dev->ep_dev_type = DPAA2_MAC; - else if (!strcmp(endpoint2.type, "dpni")) - dev->ep_dev_type = DPAA2_ETH; - else if (!strcmp(endpoint2.type, "dpdmux")) - dev->ep_dev_type = DPAA2_MUX; - else - dev->ep_dev_type = DPAA2_UNKNOWN; - - dev->ep_object_id = endpoint2.id; - } else { - dev->ep_dev_type = DPAA2_UNKNOWN; - } - sprintf(dev->ep_name, "%s.%d", endpoint2.type, endpoint2.id); - } TAILQ_INSERT_TAIL(&dprc_dev_list, dprc_node, next); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 27ddb106c8..5dcc12b19a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3912,6 +3912,55 @@ dpaa2_get_devargs(struct rte_devargs *devargs, const char *key) return 1; } +/* Resolve the object this DPNI is wired to inside its DPRC container. The + * endpoint decides whether MAC-level operations (link, promisc, flow control) + * are available, and it is reported to the application by + * rte_pmd_dpaa2_ep_name(). + */ +static int +dpaa2_dev_ep_init(struct rte_dpaa2_device *dpaa2_dev, + struct dpaa2_dev_priv *priv) +{ + struct dpaa2_dprc_dev *dprc_node = dpaa2_dev->container; + struct dprc_endpoint endpoint1, endpoint2; + int link_state, ret; + + memset(&endpoint1, 0, sizeof(endpoint1)); + memset(&endpoint2, 0, sizeof(endpoint2)); + strlcpy(endpoint1.type, "dpni", sizeof(endpoint1.type)); + endpoint1.id = dpaa2_dev->object_id; + ret = dprc_get_connection(&dprc_node->dprc, CMD_PRI_LOW, + dprc_node->token, &endpoint1, &endpoint2, + &link_state); + if (ret != 0) + return ret; + + if (strcmp(endpoint2.type, "dpmac") == 0) + priv->ep_dev_type = DPAA2_MAC; + else if (strcmp(endpoint2.type, "dpni") == 0) + priv->ep_dev_type = DPAA2_ETH; + else if (strcmp(endpoint2.type, "dpdmux") == 0) + priv->ep_dev_type = DPAA2_MUX; + else if (strcmp(endpoint2.type, "dpsw") == 0) + priv->ep_dev_type = DPAA2_SW; + else + priv->ep_dev_type = DPAA2_UNKNOWN; + + priv->ep_object_id = endpoint2.id; + + /* dpdmux and dpsw endpoints are per-interface, so the interface index + * is part of the name. + */ + if (priv->ep_dev_type == DPAA2_MUX || priv->ep_dev_type == DPAA2_SW) + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d.%d", + endpoint2.type, endpoint2.id, endpoint2.if_id); + else + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d", + endpoint2.type, endpoint2.id); + + return 0; +} + static int dpaa2_dev_init(struct rte_eth_dev *eth_dev) { @@ -4005,6 +4054,13 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + ret = dpaa2_dev_ep_init(dpaa2_dev, priv); + if (ret) { + DPAA2_PMD_ERR("Failure in get dpni@%d endpoint, err code %d", + hw_id, ret); + goto init_err; + } + ret = dpni_get_api_version(dpni_dev, CMD_PRI_LOW, &priv->dpni_ver_major, &priv->dpni_ver_minor); if (ret) { @@ -4239,7 +4295,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; DPAA2_PMD_INFO("%s: netdev created, connected to %s", - eth_dev->data->name, dpaa2_dev->ep_name); + eth_dev->data->name, priv->ep_name); priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index ed038c204b..acf4a8b320 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -628,18 +628,18 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_MAC) { + if (priv->ep_dev_type == DPAA2_MAC) { /** For dpmac-dpni connection, * try setting serdes loopback as recycle device at first. */ if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; @@ -668,8 +668,8 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_ETH && - dpaa2_dev->object_id == dpaa2_dev->ep_object_id) { + if (priv->ep_dev_type == DPAA2_ETH && + dpaa2_dev->object_id == priv->ep_object_id) { priv->flags |= DPAA2_TX_DPNI_LOOPBACK_MODE; return 0; @@ -682,7 +682,6 @@ int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) { struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct rte_dpaa2_device *dpaa2_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *dpaa2_dev); struct fsl_mc_io *dpni_dev = eth_dev->process_private; struct dpni_port_cfg port_cfg; int ret = 0; @@ -692,7 +691,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) if (priv->flags & DPAA2_TX_SERDES_LOOPBACK_MODE) { if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); @@ -700,7 +699,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 43/47] drivers: align dpaa2 event port depths with hardware rings 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (41 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 42/47] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 44/47] net/dpaa2: read MC version from device private data Prashant Gupta ` (4 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Hemant Agrawal <hemant.agrawal@nxp.com> The event port dequeue and enqueue depths were fixed at 8. A dequeue drains the portal DQRR and an enqueue fills the EQCR, so the real limits are the sizes of those two rings, which differ per SoC and are known at run time. Report them instead, adding qbman_swp_portal_dqrr_size() to query the DQRR size (the EQCR size is already available as dpaa2_eqcr_size). The Tx adapter enqueue helpers sized their on-stack mbuf arrays from the advertised enqueue depth, which no longer bounds the burst the adapter may hand them, so bound the copy by the array itself and transmit in chunks. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- .../fslmc/qbman/include/fsl_qbman_portal.h | 7 ++ drivers/bus/fslmc/qbman/qbman_portal.c | 15 ++++ drivers/event/dpaa2/dpaa2_eventdev.c | 72 ++++++++++++------- drivers/event/dpaa2/dpaa2_eventdev.h | 4 +- 4 files changed, 69 insertions(+), 29 deletions(-) diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index 73e57bcdc1..fb1c6046ae 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -1222,6 +1222,13 @@ __rte_internal int qbman_swp_acquire(struct qbman_swp *s, uint16_t bpid, uint64_t *buffers, unsigned int num_buffers); +/** + * qbman_swp_portal_dqrr_size() - Number of entries in a portal's DQRR. + * @p: the software portal object, NULL to query the SoC's DQRR size. + */ +__rte_internal +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p); + /*****************/ /* FQ management */ /*****************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index 64b61a5551..85d34b25ca 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -73,6 +73,11 @@ enum qbman_sdqcr_fc { static struct qbman_swp *portal_idx_map[MAX_QBMAN_PORTALS]; uint32_t qman_version; +/* DQRR size of the portals initialised so far. All portals of a SoC have the + * same size, so this doubles as the SoC's DQRR size for callers that have no + * portal at hand. + */ +static uint32_t dpaa2_portal_dqrr_size = 8; /* Internal Function declaration */ static int @@ -239,6 +244,15 @@ static int (*qbman_swp_release_ptr)(struct qbman_swp *s, const uint64_t *buffers, unsigned int num_buffers) = qbman_swp_release_direct; +RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_portal_dqrr_size) +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p) +{ + if (p != NULL) + return p->dqrr.dqrr_size; + + return dpaa2_portal_dqrr_size; +} + /*********************************/ /* Portal constructor/destructor */ /*********************************/ @@ -303,6 +317,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) p->dqrr.ci_vec_en = p->dqrr.dqrr_size <= (32 - DQRR_DCAP_CI_VEC_OFFSET); p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; + dpaa2_portal_dqrr_size = p->dqrr.dqrr_size; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 5d32bd9fd6..ddcf7b3678 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017,2019-2022 NXP + * Copyright 2017,2019-2022,2026 NXP */ #include <assert.h> @@ -389,10 +389,11 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, /* we only support dpio up to number of cores */ if (dev_info->max_event_ports > rte_lcore_count()) dev_info->max_event_ports = rte_lcore_count(); - dev_info->max_event_port_dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - dev_info->max_event_port_enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + /* A dequeue drains the portal DQRR and an enqueue fills the EQCR, so + * the hardware ring sizes are the real limits. + */ + dev_info->max_event_port_dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + dev_info->max_event_port_enqueue_depth = dpaa2_eqcr_size; dev_info->max_num_events = DPAA2_EVENT_MAX_NUM_EVENTS; dev_info->event_dev_cap = RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED | RTE_EVENT_DEV_CAP_ATOMIC | @@ -527,12 +528,9 @@ dpaa2_eventdev_port_def_conf(struct rte_eventdev *dev, uint8_t port_id, RTE_SET_USED(dev); RTE_SET_USED(port_id); - port_conf->new_event_threshold = - DPAA2_EVENT_MAX_NUM_EVENTS; - port_conf->dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - port_conf->enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + port_conf->new_event_threshold = DPAA2_EVENT_MAX_NUM_EVENTS; + port_conf->dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + port_conf->enqueue_depth = dpaa2_eqcr_size; port_conf->event_port_cfg = 0; } @@ -977,18 +975,31 @@ dpaa2_eventdev_txa_enqueue_same_dest(void *port, struct rte_event ev[], uint16_t nb_events) { - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH], *m0; - uint8_t qid, i; + struct rte_mbuf *m[MAX_TX_RING_SLOTS], *m0; + uint16_t sent = 0, burst, i, port_id; + uint8_t qid; RTE_SET_USED(port); - m0 = (struct rte_mbuf *)ev[0].mbuf; + m0 = ev[0].mbuf; qid = rte_event_eth_tx_adapter_txq_get(m0); + port_id = m0->port; + + /* The advertised enqueue depth is the EQCR size, which may exceed the + * on-stack burst array, so transmit in ring-sized chunks. + */ + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) + m[i] = ev[sent + i].mbuf; + + i = rte_eth_tx_burst(port_id, qid, m, burst); + sent += i; + if (i < burst) + break; + } - for (i = 0; i < nb_events; i++) - m[i] = (struct rte_mbuf *)ev[i].mbuf; - - return rte_eth_tx_burst(m0->port, qid, m, nb_events); + return sent; } static uint16_t @@ -996,19 +1007,28 @@ dpaa2_eventdev_txa_enqueue(void *port, struct rte_event ev[], uint16_t nb_events) { - void *txq[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - uint8_t qid, i; + void *txq[MAX_TX_RING_SLOTS]; + struct rte_mbuf *m[MAX_TX_RING_SLOTS]; + uint16_t sent = 0, burst, i; + uint8_t qid; RTE_SET_USED(port); - for (i = 0; i < nb_events; i++) { - m[i] = (struct rte_mbuf *)ev[i].mbuf; - qid = rte_event_eth_tx_adapter_txq_get(m[i]); - txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) { + m[i] = ev[sent + i].mbuf; + qid = rte_event_eth_tx_adapter_txq_get(m[i]); + txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + } + + i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); + sent += i; + if (i < burst) + break; } - return dpaa2_dev_tx_multi_txq_ordered(txq, m, nb_events); + return sent; } static struct eventdev_ops dpaa2_eventdev_ops = { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index 3883a26c91..a054dfdbd7 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017 NXP + * Copyright 2017,2026 NXP */ #ifndef __DPAA2_EVENTDEV_H__ @@ -22,8 +22,6 @@ #define DPAA2_EVENT_MAX_QUEUE_FLOWS 2048 #define DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS 8 #define DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS 0 -#define DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH 8 -#define DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH 8 #define DPAA2_EVENT_MAX_NUM_EVENTS (INT32_MAX - 1) #define DPAA2_EVENT_QUEUE_ATOMIC_FLOWS 2048 -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 44/47] net/dpaa2: read MC version from device private data 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (42 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 43/47] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 45/47] net/dpaa2: do not overwrite mbuf hash with drop priority Prashant Gupta ` (3 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev From: Hemant Agrawal <hemant.agrawal@nxp.com> The flow engine reached back to the bus device to read the MC firmware version. The bus_info pointer behind it is only attached by the primary process, so a secondary process that creates a flow dereferences a pointer it never set up. The version is already cached in priv->mc_rev at probe time and the rest of the driver reads it from there, so use that here too. This removes the last user of DPAA2_DEV_PRIV_TO_DPAA2_DEV(), so drop the macro. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 4 --- drivers/net/dpaa2/dpaa2_flow.c | 61 ++++++++++---------------------- 2 files changed, 19 insertions(+), 46 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 0934e04198..82021ec87e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -44,10 +44,6 @@ #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 -#define DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv) \ - container_of((((struct dpaa2_dev_priv *)priv)->eth_dev->device), \ - struct rte_dpaa2_device, device) - #define DPAA2_EXTRACT_PARAM_MAX_SIZE \ RTE_ALIGN(sizeof(struct dpni_ext_set_rx_tc_dist), 256) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index a51225d38d..c1ee7f4bc4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -795,13 +795,10 @@ static int dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, struct dpaa2_generic_flow *flow) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_flow_tbl_profile *tbl_profile; int ret; struct fsl_mc_io *dpni = priv->hw; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - tbl_profile = &priv->flow_profile.tc_profile[flow->tc_id]; if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, flow->entry_index)) { @@ -812,7 +809,7 @@ dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, dpaa2_flow_fs_entry_log("Add", flow); - if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { + if (priv->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token, flow->tc_id, flow->entry_index, &flow->rule_cfg, &flow->flow_action.fs_action.fs_action_cfg); @@ -3671,7 +3668,6 @@ dpaa2_flow_fs_action_config(struct dpaa2_dev_priv *priv, struct dpaa2_generic_flow *flow, const struct rte_flow_action *rte_action) { - struct rte_dpaa2_device *dpaa2_dev; struct rte_eth_dev *dest_dev; struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; @@ -3680,11 +3676,9 @@ dpaa2_flow_fs_action_config(struct dpaa2_dev_priv *priv, uint16_t num_tokens; struct dpaa2_dev_flow_fs_action *fs_action; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - fs_action = &flow->flow_action.fs_action; if (fs_action->action_type != RTE_FLOW_ACTION_TYPE_END) { - if (dpaa2_dev->bus_info->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV && + if (priv->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV && (fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || fs_action->action_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR)) { if (rte_action->type != RTE_FLOW_ACTION_TYPE_PORT_ID && @@ -3836,21 +3830,19 @@ dpaa2_flow_fs_table_set_default(struct dpaa2_dev_priv *priv, uint8_t tc_id, int discard, uint16_t default_queue) { int ret; - struct rte_dpaa2_device *dpaa2_dev; struct dpni_rx_dist_cfg *tc_cfg; struct fsl_mc_io *dpni = priv->hw; struct dpaa2_flow_tbl_profile *tbl_profile; struct dpaa2_queue *queue; char mc_rev[1024]; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); tbl_profile = &priv->flow_profile.tc_profile[tc_id]; snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", - RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + RTE_FSL_MC_REV_MAJOR(priv->mc_rev), + RTE_FSL_MC_REV_MINOR(priv->mc_rev), + RTE_FSL_MC_REV_REVISION(priv->mc_rev)); if (!tbl_profile->dpkg.num_extracts && - dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { DPAA2_PMD_DEBUG("%s can't set miss action of FS table indepentently.", mc_rev); return 0; @@ -3975,26 +3967,24 @@ dpaa2_flow_qos_table_set_default(struct dpaa2_dev_priv *priv, int discard, uint8_t default_tc, uint16_t default_flow) { int ret; - struct rte_dpaa2_device *dpaa2_dev; struct dpni_qos_tbl_cfg qos_cfg; struct fsl_mc_io *dpni = priv->hw; struct dpaa2_flow_tbl_profile *tbl_profile; char mc_rev[1024]; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); tbl_profile = &priv->flow_profile.qos_profile; snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", - RTE_FSL_MC_REV_MAJOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_MINOR(dpaa2_dev->bus_info->mc_rev), - RTE_FSL_MC_REV_REVISION(dpaa2_dev->bus_info->mc_rev)); + RTE_FSL_MC_REV_MAJOR(priv->mc_rev), + RTE_FSL_MC_REV_MINOR(priv->mc_rev), + RTE_FSL_MC_REV_REVISION(priv->mc_rev)); if (!tbl_profile->dpkg.num_extracts && - dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { DPAA2_PMD_DEBUG("%s can't set miss action of QoS table indepentently.", mc_rev); return 0; } if (default_flow < priv->dist_queues && - dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) { + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) { DPAA2_PMD_WARN("%s can't direct miss traffic to TC%d-flow%d by QoS table only.", mc_rev, default_tc, default_flow); return 0; @@ -4031,7 +4021,6 @@ static int dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, int rss_dist) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_flow_tbl_profile *tbl_profile; uint8_t *key_cfg_buf; int ret; @@ -4093,8 +4082,7 @@ dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, qos_cfg->discard_on_miss = false; } - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - if (dpaa2_dev->bus_info->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) + if (priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, priv->token, qos_cfg); else ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, qos_cfg); @@ -4238,7 +4226,6 @@ static int dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, uint8_t tc_id, const struct rte_flow_action_meter_mark *meter_mark) { - struct rte_dpaa2_device *dpaa2_dev; struct dpni_rx_tc_policing_cfg policing_cfg = {0}; const struct dpaa2_dev_meter_profile *dpaa2_profile; const struct dpaa2_dev_meter_policy *dpaa2_policy = NULL; @@ -4250,8 +4237,6 @@ dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, return -ENOTSUP; } - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - dpaa2_profile = (void *)meter_mark->profile; if (!dpaa2_profile) { DPAA2_PMD_ERR("Meter profile not specified!"); @@ -4273,9 +4258,8 @@ dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, if (priv->flow_profile.mtr_flow[tc_id]) { /** Update existing policer.*/ - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - policing_cfg.options |= DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS; - if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV) + policing_cfg.options |= DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS; + if (priv->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV) DPAA2_PMD_WARN("The existing policer's counters will be cleaned."); } @@ -4298,7 +4282,7 @@ dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, policing_cfg.eir = dpaa2_profile->pir; policing_cfg.ebs = dpaa2_profile->pbs; - if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + if (priv->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, priv->token, tc_id, &policing_cfg); } else { @@ -5429,7 +5413,6 @@ dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev, int mix_extract, int is_rss) { struct dpaa2_generic_flow *flow = NULL; - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_dev_priv *priv = dev->data->dev_private; int ret, idx = -1; uint64_t iova, mc_rev; @@ -5445,8 +5428,7 @@ dpaa2_flow_generic_flow_create(struct rte_eth_dev *dev, if (type != DPAA2_FLOW_QOS_TYPE && type != DPAA2_FLOW_FS_TYPE) return NULL; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - mc_rev = dpaa2_dev->bus_info->mc_rev; + mc_rev = priv->mc_rev; if (actions) { ret = dpaa2_flow_qos_fs_action_set(actions, qos_actions, @@ -5941,19 +5923,17 @@ static int dpaa2_flow_destroy_meter_flow(struct rte_eth_dev *dev, struct dpaa2_dev_flow *flow) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpni_rx_tc_policing_cfg cfg; int ret; uint8_t tc_id; RTE_ASSERT(!flow->qos_flow && flow->fs_flow); - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); tc_id = flow->fs_flow->tc_id; RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == flow); memset(&cfg, 0, sizeof(cfg)); cfg.mode = DPNI_POLICER_MODE_NONE; - if (dpaa2_dev->bus_info->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + if (priv->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, priv->token, tc_id, &cfg); } else { @@ -6170,7 +6150,6 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, const struct rte_flow_action actions[], struct rte_flow_error *error) { - struct rte_dpaa2_device *dpaa2_dev; struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_dev_flow *flow; struct dpaa2_flow_tbl_profile *tbl_profile = NULL; @@ -6191,8 +6170,6 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, const struct rte_flow_action_queue *action_q; struct dpaa2_queue *rxq = NULL; - dpaa2_dev = DPAA2_DEV_PRIV_TO_DPAA2_DEV(priv); - /* check for the valid flow */ flow = (void *)_flow; if (flow->is_meter_flow) { @@ -6304,7 +6281,7 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, if (fs_action_num > 0 && fs_actions[0].type != RTE_FLOW_ACTION_TYPE_PORT_ID && fs_actions[0].type != RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT && - dpaa2_dev->bus_info->mc_rev >= DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV) { + priv->mc_rev >= DPAA2_FS_FLOW_HW_ACTION_UPDATE_MC_REV) { /** Action HW update doesn't support redirecting frames to other DPNIs.*/ hw_update = true; goto skip_remove_fs_entry; @@ -6394,7 +6371,7 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, } hw_update = false; - if (dpaa2_dev->bus_info->mc_rev >= DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV) { + if (priv->mc_rev >= DPAA2_QOS_FLOW_HW_ACTION_UPDATE_MC_REV) { /** Action HW update doesn't support redirecting frames to other DPNIs.*/ hw_update = true; goto skip_remove_qos_entry; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 45/47] net/dpaa2: do not overwrite mbuf hash with drop priority 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (43 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 44/47] net/dpaa2: read MC version from device private data Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 46/47] bus/fslmc: reduce probe-time logging and MC traffic Prashant Gupta ` (2 subsequent siblings) 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Hemant Agrawal <hemant.agrawal@nxp.com> dpaa2_eth_fd_to_mbuf() wrote the frame descriptor's drop priority into mbuf->hash.sched.color unconditionally. hash.sched shares the union with hash.rss and hash.fdir, so this clobbered whatever the parse step had placed there. The scheduler color is only meaningful when the frame came out of a flow-steering table, and dpaa2_dev_rx_mbuf_sched_set() already sets the whole sched field (queue, traffic class and colour) in that case, so drop the unconditional write. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_rxtx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 6d17a4d160..7c2c484b8c 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -488,7 +488,6 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) mbuf->pkt_len = mbuf->data_len; mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; - mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf), -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 46/47] bus/fslmc: reduce probe-time logging and MC traffic 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (44 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 45/47] net/dpaa2: do not overwrite mbuf hash with drop priority Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 47/47] net/dpaa2: reject Rx queue deferred start Prashant Gupta 2026-09-10 16:57 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Stephen Hemminger 47 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Every DMA map logged its virtual, IOVA and physical addresses at NOTICE. An application that maps many memory segments prints one such line per segment during initialisation, which drowns out messages the operator actually needs; the neighbouring mapping paths already use debug level. fslmc_vfio_get_bus_info() also issued mc_get_soc_version() twice in a row into the same structure, so the second command only overwrote the first result with an identical one. Keep a single query. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/bus/fslmc/fslmc_vfio.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index 4eb8552696..5ccb457a75 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -281,13 +281,6 @@ fslmc_vfio_get_bus_info(void *regs, struct rte_fslmc_bus_info *bus_info) return ret; } - memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); - ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); - if (ret) { - DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); - return ret; - } - for (i = 0; i < RTE_DIM(s_soc_type); i++) { if ((mc_plat_info.svr & DPAA2_SVR_MASK) == s_soc_type[i].svr) { dpaa2_svr_family = s_soc_type[i].svr; @@ -1041,8 +1034,7 @@ fslmc_map_dma(uint64_t vaddr, rte_iova_t iovaddr, size_t len) fslmc_mem_va2iova = RTE_BAD_IOVA; TAILQ_INSERT_TAIL(&fslmc_memsegs, dmaseg, next); } - DPAA2_BUS_LOG(NOTICE, - "%s(%zx): VA(%" PRIx64 "):IOVA(%" PRIx64 "):PHY(%" PRIx64 ")", + DPAA2_BUS_DEBUG("%s(%zx): VA(%" PRIx64 "):IOVA(%" PRIx64 "):PHY(%" PRIx64 ")", is_io ? "DMA I/O map size" : "DMA MEM map size", len, vaddr, iovaddr, phy); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v2 47/47] net/dpaa2: reject Rx queue deferred start 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (45 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 46/47] bus/fslmc: reduce probe-time logging and MC traffic Prashant Gupta @ 2026-09-10 13:51 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 2026-09-10 16:57 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Stephen Hemminger 47 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-09-10 13:51 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The driver has no way to hold an Rx queue down while the port is started, and dpaa2_rxq_info_get() already reports rx_deferred_start as 0. The Tx side rejects the request; do the same for Rx instead of silently accepting a configuration that will not be honoured. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 5dcc12b19a..6e16e7a84b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1424,6 +1424,13 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, DPAA2_PMD_DEBUG("dev =%p, queue =%d, pool = %p, conf =%p", dev, rx_queue_id, mb_pool, rx_conf); + /* Rx deferred start is not supported */ + if (rx_conf->rx_deferred_start) { + DPAA2_PMD_ERR("%s: Rx deferred start not supported", + dev->data->name); + return -EINVAL; + } + total_nb_rx_desc += nb_rx_desc; if (total_nb_rx_desc > MAX_NB_RX_DESC_IN_PEB && (priv->options & DPNI_OPT_V1_PFDR_IN_PEB)) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features 2026-09-10 13:51 ` [PATCH v2 47/47] net/dpaa2: reject Rx queue deferred start Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (15 more replies) 0 siblings, 16 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev This is the second of four series upstreaming the missing NXP dpaa2 driver changes. It does not depend on series 1 and can be applied independently. It adds the net/dpaa2 flow, metering and parser features: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, meter and policing, and the flow drop action, with a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - restructure the parser processing, parse tunnel and fragmented packet types, remove the unused soft parser driver and rename the Rx queue flags. Every commit builds cleanly (including the aarch64 DPAA cross build with -Werror) and the series is bisectable. Gagandeep Singh (7): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (4): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 3 + doc/guides/rel_notes/release_26_11.rst | 6 + drivers/net/dpaa2/dpaa2_ethdev.c | 82 +- drivers/net/dpaa2/dpaa2_ethdev.h | 212 +++- drivers/net/dpaa2/dpaa2_flow.c | 268 +++- drivers/net/dpaa2/dpaa2_meter.c | 579 +++++++++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1539 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_recycle.c | 28 +- drivers/net/dpaa2/dpaa2_rxtx.c | 334 +++-- drivers/net/dpaa2/dpaa2_sparser.c | 137 -- drivers/net/dpaa2/dpaa2_sparser.h | 202 --- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 31 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 2 +- 19 files changed, 2911 insertions(+), 984 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v3-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (14 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is defined as sysconf(_SC_PAGESIZE) which may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). Use sysconf() explicitly with a signed long, check for errors, and compute map_len separately with unsigned arithmetic before passing to mmap. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..f1a234deae 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,28 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + len = len & page_mask; + + map_len = len; + if (map_len < (size_t)page_size) + map_len = (size_t)page_size; - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 02/13] net/dpaa2: set Tx confirmation on device init 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta ` (13 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f211357919..c95704d4ca 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3624,6 +3599,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 03/13] net/dpaa2: support larger burst size 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (12 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (2 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta ` (11 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..90e0b66258 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 05/13] net/dpaa2: support meter and policing 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (3 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta ` (10 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API to the dpaa2 PMD. The implementation registers the rte_mtr operations through the ".mtr_ops_get" dev_ops hook and maintains software bookkeeping of meter profiles, policies and meter objects under a per-device spinlock. Supported algorithms are trTCM RFC 2698 and trTCM RFC 4115 in both byte and packet modes. Meter policies support drop and pass-through actions on the red color. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 1 + doc/guides/rel_notes/release_26_11.rst | 6 + drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_ethdev.h | 29 ++ drivers/net/dpaa2/dpaa2_meter.c | 579 +++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 23 +- drivers/net/dpaa2/meson.build | 1 + 8 files changed, 638 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index ae8b32af2c..faee3a72a2 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -407,6 +407,7 @@ Features of the DPAA2 PMD are: - Link flow control - Scattered and gather for TX and RX - Rx queue interrupts +- Traffic metering and policing - :ref:`dpaa2_dptmapi` diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..4936769191 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -19,6 +19,7 @@ RSS hash = Y RSS reta update = Y VLAN filter = Y Flow control = Y +Rate limitation = Y Traffic manager = Y VLAN offload = Y L3 checksum offload = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index c8cc86295d..eae26f430c 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -55,6 +55,12 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Updated NXP DPAA2 net driver.** + + * Added support for flow classification on more protocol fields. + * Added Tx queue based flow control and confirmation queue handling. + * Added software parser based packet dump for debugging. + * Added support for traffic metering and policing. Removed Items ------------- diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c95704d4ca..d23c73b21d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3320,6 +3320,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, @@ -3543,6 +3544,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->num_channels = attr.num_channels; priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..e329111c0b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + bool red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -411,6 +435,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -456,6 +481,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -548,6 +576,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..7091d172d8 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,579 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = true, + .color_aware_trtcm_rfc4115_supported = true, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Policer profile alg not supported!"); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /** Align with DPNI policy.*/ + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + dpaa2_profile->profile_id = profile_id; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + RTE_SET_USED(dev); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..d227025e01 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ +#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004 + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1132,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1183,18 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); +int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 06/13] net/dpaa2: support flow drop action 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (4 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta ` (9 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 90e0b66258..b2f1778de3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 07/13] net/dpaa2: set default flow miss action per device 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (5 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (8 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global configured only via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable and defaulted to 0. Replace it with a per-device default_flow computed at probe time as the lowest priority flow of the FS table, so that unmatched frames are directed there without depending on an environment variable. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index d23c73b21d..70f271ec45 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3543,6 +3543,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MIN(priv->fs_entries, + priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); rte_spinlock_init(&priv->meter_lock); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e329111c0b..58a47cd1a2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b2f1778de3..2e844121a8 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (6 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta ` (7 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC for mbuf Rx scheduling. An Rx mbuf received from the FS table is marked with RTE_MBUF_F_RX_FDIR along with the TC and flow ID decoded from the FLC low word. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 58a47cd1a2..76a04c5858 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e844121a8..45660df31a 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..7ba6a4563f 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, 0); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 09/13] net/dpaa2: add minimum key size support 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (7 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (6 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 45660df31a..2662c358e4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4532,8 +4535,7 @@ dpaa2_flow_entry_size(uint16_t key_max_size) if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 10/13] net/dpaa2: restructure dpaa2 parser processing 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (8 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (5 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move the parse-result decoding into a dedicated header so that the hardware parser fields are described in one place and shared between the flow code and the Rx path. No functional change is intended. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 172 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1539 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 332 ++--- 5 files changed, 1906 insertions(+), 578 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 76a04c5858..09fa158918 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,17 +207,33 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; -extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ @@ -258,42 +308,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -435,6 +449,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -474,6 +489,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -482,6 +500,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -513,6 +532,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..f180955b15 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1539 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_L4_NONFRAG; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type &= ~RTE_PTYPE_L4_NONFRAG; + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 7ba6a4563f..47c8cacdc4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,19 +26,43 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" +#include "dpaa2_parser_decode.h" -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} -static inline rte_mbuf_timestamp_t * -dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) { - return RTE_MBUF_DYNFIELD(mbuf, - dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; } #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ @@ -51,95 +75,108 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) + +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, DPAA2_GET_FD_DROPP(fd)); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + RTE_SET_USED(priv); m->packet_type = RTE_PTYPE_UNKNOWN; + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); - } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - m->ol_flags |= RTE_MBUF_F_RX_FDIR; - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - rte_mbuf_sched_set(m, flow, tc, 0); - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + m->packet_type = dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; } - if (dpaa2_enable_ts[m->port]) { - *dpaa2_timestamp_dynfield(m) = annotation->word2; - m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + *(rte_be64_t *)&word5 = rte_cpu_to_be_64(annotation->word5); + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -249,36 +286,18 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + annotation->word4); - if (dpaa2_enable_ts[mbuf->port]) { - *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; - mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(mbuf)); - } + RTE_SET_USED(priv); /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -307,8 +326,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -336,12 +354,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -381,13 +401,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -397,7 +426,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -413,9 +442,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -674,6 +704,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -729,15 +760,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -792,18 +824,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -909,18 +935,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -989,7 +1014,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1014,7 +1042,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1041,7 +1072,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1151,12 +1185,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1164,6 +1201,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1314,7 +1352,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1336,7 +1374,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1617,8 +1655,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (9 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (4 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend the Rx parser to identify additional packet types decoded from the hardware parser summary: IPv4/IPv6 fragments, IPsec ESP, and GTP-U / GTP-C tunnels. The corresponding DPAA2_PKT_TYPE_* values are added and mapped to the matching RTE_PTYPE_* flags in the slow-path parser. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 09fa158918..6ea4a133ea 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 47c8cacdc4..26c84e7125 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -153,6 +153,38 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPC; + break; case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 12/13] net/dpaa2: remove unused soft parser driver 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (10 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta ` (3 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Softparser only supports to be loaded before Linux starts. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 28 ----- drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 -------------------- drivers/net/dpaa2/dpaa2_sparser.h | 202 ------------------------------ drivers/net/dpaa2/meson.build | 1 - 5 files changed, 369 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 70f271ec45..e2e580b5fc 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3719,33 +3718,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f1a234deae..7569ea9c0d 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S2 13/13] net/dpaa2: rename Rx queue flags 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (11 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-09-15 11:34 ` Prashant Gupta 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (2 subsequent siblings) 15 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 11:34 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change; it prepares the flag namespace for the Tx confirmation rework that follows. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index e2e580b5fc..4be804a995 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1517,7 +1517,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3475,7 +3475,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3582,7 +3582,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 6ea4a133ea..3ed7ab50a3 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,10 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) + +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 26c84e7125..d07db3869a 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -860,7 +860,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1132,7 +1132,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (12 preceding siblings ...) 2026-09-15 11:34 ` [PATCH v3-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-09-15 12:01 ` Prashant Gupta 2026-09-15 12:01 ` [PATCH v3-S3 01/10] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta ` (10 more replies) 2026-09-15 15:42 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta 15 siblings, 11 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:01 UTC (permalink / raw) To: stephen, dev This is the third of four dpaa2 upstreaming sub-series, applied on top of v3-S1 and v3-S2. It reworks the fslmc bus, DMA, eventdev and the net datapath. Highlights: - add a DMA bypass memory translation option and optimize the Tx queue and channel mapping; - refresh the MC and SoC version information and identify the soft parser protocol; - assign the Rx CGID per traffic class and inherit the rxq config for the event queue; - rework Tx confirmation and consume DQRR entries in batches; - resolve the dpaa2 endpoint in the net driver and align the event port depths with the hardware rings. Every commit builds cleanly (arm64, -Werror) and the series is bisectable. Depends-on: series-39291 ("net/dpaa2: flow, meter and parser features") Gagandeep Singh (2): drivers: add dpaa2 DMA bypass memory translation option drivers: optimize dpaa2 Tx queue and channel mapping Jun Yang (8): drivers: refresh dpaa2 MC and SoC version info drivers: identify dpaa2 soft parser protocol drivers: assign dpaa2 Rx CGID per traffic class drivers: inherit dpaa2 rxq config for event queue drivers: rework dpaa2 Tx confirmation drivers: consume dpaa2 DQRR entries in batches drivers: resolve dpaa2 endpoint in the net driver drivers: align dpaa2 event port depths with hardware rings doc/guides/nics/dpaa2.rst | 16 +- drivers/bus/fslmc/bus_fslmc_driver.h | 15 +- drivers/bus/fslmc/fslmc_bus.c | 93 +- drivers/bus/fslmc/fslmc_vfio.c | 193 ++- drivers/bus/fslmc/fslmc_vfio.h | 30 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 83 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 7 - drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 45 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 7 +- drivers/bus/fslmc/private.h | 3 + .../fslmc/qbman/include/fsl_qbman_portal.h | 12 +- drivers/bus/fslmc/qbman/qbman_portal.c | 78 +- drivers/bus/fslmc/qbman/qbman_portal.h | 11 +- drivers/common/dpaax/rte_pmd_dpaax_qdma.h | 4 +- drivers/dma/dpaa2/dpaa2_qdma.c | 87 +- drivers/event/dpaa2/dpaa2_eventdev.c | 76 +- drivers/event/dpaa2/dpaa2_eventdev.h | 4 +- drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 2 +- drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 516 +++--- drivers/net/dpaa2/dpaa2_ethdev.h | 38 +- drivers/net/dpaa2/dpaa2_flow.c | 129 +- drivers/net/dpaa2/dpaa2_ptp.c | 4 +- drivers/net/dpaa2/dpaa2_recycle.c | 15 +- drivers/net/dpaa2/dpaa2_rxtx.c | 1515 ++++++++--------- 25 files changed, 1579 insertions(+), 1410 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v3-S3 01/10] drivers: add dpaa2 DMA bypass memory translation option 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta @ 2026-09-15 12:01 ` Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 02/10] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta ` (9 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:01 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add RTE_DPAAX_QDMA_BMT_FLAG flag to allow callers to bypass memory translation (BMT) for DMA operations. This is needed for some PCIe scenarios where IOMMU translation should be skipped. The flag is propagated to all SG entry and FD populate helpers via a new 'bmt' parameter, defaulting to DISABLE when the flag is not set. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/common/dpaax/rte_pmd_dpaax_qdma.h | 4 +- drivers/dma/dpaa2/dpaa2_qdma.c | 87 ++++++++++++----------- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/drivers/common/dpaax/rte_pmd_dpaax_qdma.h b/drivers/common/dpaax/rte_pmd_dpaax_qdma.h index 8f2fc83f8d..6bd72b0b0e 100644 --- a/drivers/common/dpaax/rte_pmd_dpaax_qdma.h +++ b/drivers/common/dpaax/rte_pmd_dpaax_qdma.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2021-2024 NXP + * Copyright 2021-2024, 2026 NXP */ #ifndef RTE_PMD_DPAAX_QDMA_H @@ -7,6 +7,8 @@ #include <rte_compat.h> +#define RTE_DPAAX_QDMA_BMT_FLAG RTE_BIT64(7) + #define RTE_DPAAX_QDMA_COPY_IDX_OFFSET 8 #define RTE_DPAAX_QDMA_SG_IDX_ADDR_ALIGN \ RTE_BIT64(RTE_DPAAX_QDMA_COPY_IDX_OFFSET) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 401ab56f39..10fc50b8fe 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -273,7 +273,7 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd, } static void -sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) +sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx, int bmt) { uint16_t i; struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; @@ -283,23 +283,17 @@ sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx) /* source SG */ src_sge[i].ctrl.sl = QDMA_SG_SL_LONG; src_sge[i].ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - src_sge[i].ctrl.bmt = QDMA_SG_BMT_DISABLE; + src_sge[i].ctrl.bmt = bmt; /* destination SG */ dst_sge[i].ctrl.sl = QDMA_SG_SL_LONG; dst_sge[i].ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - dst_sge[i].ctrl.bmt = QDMA_SG_BMT_DISABLE; + dst_sge[i].ctrl.bmt = bmt; } } static int fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, - struct qdma_virt_queue *qdma_vq) + struct qdma_virt_queue *qdma_vq, int bmt) { struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry; struct qdma_sg_entry *dst_sge = sg_cntx->sg_dst_entry; @@ -327,7 +321,7 @@ fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, return -ENOMEM; } - sg_entry_pre_populate(sg_cntx); + sg_entry_pre_populate(sg_cntx, bmt); return fle_sdd_pre_populate(&sg_cntx->fle_sdd, rbp, src_sge_iova, dst_sge_iova, @@ -337,7 +331,7 @@ fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx, static inline uint32_t sg_entry_post_populate(const struct rte_dma_sge *src, const struct rte_dma_sge *dst, struct qdma_cntx_sg *sg_cntx, - uint16_t nb_sge) + uint16_t nb_sge, int bmt) { uint16_t i; uint32_t total_len = 0; @@ -350,10 +344,12 @@ sg_entry_post_populate(const struct rte_dma_sge *src, src_sge->addr_lo = (uint32_t)src[i].addr; src_sge->addr_hi = (src[i].addr >> 32); src_sge->data_len.data_len_sl0 = src[i].length; + src_sge->ctrl.bmt = bmt; dst_sge->addr_lo = (uint32_t)dst[i].addr; dst_sge->addr_hi = (dst[i].addr >> 32); dst_sge->data_len.data_len_sl0 = dst[i].length; + dst_sge->ctrl.bmt = bmt; total_len += dst[i].length; src_sge->ctrl.f = 0; @@ -368,10 +364,12 @@ sg_entry_post_populate(const struct rte_dma_sge *src, src_sge->addr_lo = (uint32_t)src[i].addr; src_sge->addr_hi = (src[i].addr >> 32); src_sge->data_len.data_len_sl0 = src[i].length; + src_sge->ctrl.bmt = bmt; dst_sge->addr_lo = (uint32_t)dst[i].addr; dst_sge->addr_hi = (dst[i].addr >> 32); dst_sge->data_len.data_len_sl0 = dst[i].length; + dst_sge->ctrl.bmt = bmt; total_len += dst[i].length; sg_cntx->job_nb = nb_sge; @@ -393,7 +391,7 @@ sg_fle_post_populate(struct qbman_fle fle[], static inline uint32_t sg_entry_populate(const struct rte_dma_sge *src, const struct rte_dma_sge *dst, struct qdma_cntx_sg *sg_cntx, - uint16_t nb_sge) + uint16_t nb_sge, int bmt) { uint16_t i; uint32_t total_len = 0; @@ -409,19 +407,13 @@ sg_entry_populate(const struct rte_dma_sge *src, src_sge->data_len.data_len_sl0 = src[i].length; src_sge->ctrl.sl = QDMA_SG_SL_LONG; src_sge->ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - src_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE; + src_sge->ctrl.bmt = bmt; dst_sge->addr_lo = (uint32_t)dst[i].addr; dst_sge->addr_hi = (dst[i].addr >> 32); dst_sge->data_len.data_len_sl0 = dst[i].length; dst_sge->ctrl.sl = QDMA_SG_SL_LONG; dst_sge->ctrl.fmt = QDMA_SG_FMT_SDB; - /** IOMMU is always on for either VA or PA mode, - * so Bypass Memory Translation should be disabled. - */ - dst_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE; + dst_sge->ctrl.bmt = bmt; total_len += src[i].length; if (i == (nb_sge - 1)) { @@ -445,7 +437,7 @@ fle_populate(struct qbman_fle fle[], struct qdma_sdd sdd[], uint64_t sdd_iova, struct dpaa2_qdma_rbp *rbp, uint64_t src_iova, uint64_t dst_iova, size_t len, - uint32_t fmt) + uint32_t fmt, int bmt) { /* first frame list to source descriptor */ DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_SDD_FLE], sdd_iova); @@ -507,11 +499,13 @@ fle_populate(struct qbman_fle fle[], * DPAA2_SET_FLE_BMT(&fle[DPAA2_QDMA_DST_FLE]); */ fle[DPAA2_QDMA_SRC_FLE].word4.fmt = fmt; + fle[DPAA2_QDMA_SRC_FLE].word4.bmt = bmt; DPAA2_SET_FLE_LEN(&fle[DPAA2_QDMA_SRC_FLE], len); /* destination frame list to destination buffer */ DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_DST_FLE], dst_iova); fle[DPAA2_QDMA_DST_FLE].word4.fmt = fmt; + fle[DPAA2_QDMA_DST_FLE].word4.bmt = bmt; DPAA2_SET_FLE_LEN(&fle[DPAA2_QDMA_DST_FLE], len); /* Final bit: 1, for last frame list */ @@ -520,12 +514,14 @@ fle_populate(struct qbman_fle fle[], static inline void fle_post_populate(struct qbman_fle fle[], - uint64_t src, uint64_t dest, size_t len) + uint64_t src, uint64_t dest, size_t len, int bmt) { DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_SRC_FLE], src); + fle[DPAA2_QDMA_SRC_FLE].word4.bmt = bmt; DPAA2_SET_FLE_LEN(&fle[DPAA2_QDMA_SRC_FLE], len); DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_DST_FLE], dest); + fle[DPAA2_QDMA_DST_FLE].word4.bmt = bmt; DPAA2_SET_FLE_LEN(&fle[DPAA2_QDMA_DST_FLE], len); } @@ -700,7 +696,9 @@ dpaa2_qdma_copy_sg(void *dev_private, if (qdma_vq->fle_pre_populate) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { - ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); + ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); if (ret) { if (!qdma_dev->is_silent) rte_mempool_put(qdma_vq->fle_pool, @@ -714,7 +712,9 @@ dpaa2_qdma_copy_sg(void *dev_private, } len = sg_entry_post_populate(src, dst, - cntx_sg, nb_src); + cntx_sg, nb_src, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); sg_fle_post_populate(fle, len); } else { sdd = cntx_sg->fle_sdd.sdd; @@ -725,11 +725,13 @@ dpaa2_qdma_copy_sg(void *dev_private, offsetof(struct qdma_cntx_sg, sg_src_entry); dst_sge_iova = cntx_iova + offsetof(struct qdma_cntx_sg, sg_dst_entry); - len = sg_entry_populate(src, dst, cntx_sg, nb_src); + len = sg_entry_populate(src, dst, cntx_sg, nb_src, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + QDMA_SG_BMT_ENABLE : QDMA_SG_BMT_DISABLE); fle_populate(fle, sdd, sdd_iova, &qdma_vq->rbp, src_sge_iova, dst_sge_iova, len, - QBMAN_FLE_WORD4_FMT_SGE); + QBMAN_FLE_WORD4_FMT_SGE, DPAA2_QDMA_BMT_DISABLE); } if (unlikely(qdma_vq->flags & DPAA2_QDMA_DESC_DEBUG_FLAG)) @@ -758,14 +760,14 @@ dpaa2_qdma_copy_sg(void *dev_private, static inline void qdma_populate_fd_pci(uint64_t src, uint64_t dest, uint32_t len, struct qbman_fd *fd, - struct dpaa2_qdma_rbp *rbp, int ser) + struct dpaa2_qdma_rbp *rbp, int ser, int bmt) { fd->simple_pci.saddr_lo = lower_32_bits(src); fd->simple_pci.saddr_hi = upper_32_bits(src); fd->simple_pci.len_sl = len; - fd->simple_pci.bmt = DPAA2_QDMA_BMT_DISABLE; + fd->simple_pci.bmt = bmt; fd->simple_pci.fmt = DPAA2_QDMA_FD_SHORT_FORMAT; fd->simple_pci.sl = 1; fd->simple_pci.ser = ser; @@ -801,14 +803,14 @@ qdma_populate_fd_pci(uint64_t src, uint64_t dest, static inline void qdma_populate_fd_ddr(uint64_t src, uint64_t dest, - uint32_t len, struct qbman_fd *fd, int ser) + uint32_t len, struct qbman_fd *fd, int ser, int bmt) { fd->simple_ddr.saddr_lo = lower_32_bits(src); fd->simple_ddr.saddr_hi = upper_32_bits(src); fd->simple_ddr.len = len; - fd->simple_ddr.bmt = DPAA2_QDMA_BMT_DISABLE; + fd->simple_ddr.bmt = bmt; fd->simple_ddr.fmt = DPAA2_QDMA_FD_SHORT_FORMAT; fd->simple_ddr.sl = 1; fd->simple_ddr.ser = ser; @@ -846,15 +848,16 @@ dpaa2_qdma_short_copy(struct qdma_virt_queue *qdma_vq, if (qdma_vq->rbp.drbp || qdma_vq->rbp.srbp) { /** PCIe EP*/ - qdma_populate_fd_pci(src, - dst, length, - fd, &qdma_vq->rbp, - is_silent ? 0 : 1); + qdma_populate_fd_pci(src, dst, length, + fd, &qdma_vq->rbp, is_silent ? 0 : 1, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } else { /** DDR or PCIe RC*/ - qdma_populate_fd_ddr(src, - dst, length, - fd, is_silent ? 0 : 1); + qdma_populate_fd_ddr(src, dst, length, + fd, is_silent ? 0 : 1, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } dpaa2_qdma_fd_save_att(fd, DPAA2_QDMA_IDX_FROM_FLAG(flags), DPAA2_QDMA_FD_SHORT); @@ -919,13 +922,17 @@ dpaa2_qdma_long_copy(struct qdma_virt_queue *qdma_vq, } } - fle_post_populate(fle, src, dst, length); + fle_post_populate(fle, src, dst, length, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } else { sdd = fle_sdd->sdd; sdd_iova = (uint64_t)sdd - qdma_vq->fle_iova2va_offset; fle_populate(fle, sdd, sdd_iova, &qdma_vq->rbp, src, dst, length, - QBMAN_FLE_WORD4_FMT_SBF); + QBMAN_FLE_WORD4_FMT_SBF, + (flags & RTE_DPAAX_QDMA_BMT_FLAG) ? + DPAA2_QDMA_BMT_ENABLE : DPAA2_QDMA_BMT_DISABLE); } if (unlikely(qdma_vq->flags & DPAA2_QDMA_DESC_DEBUG_FLAG)) -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 02/10] drivers: optimize dpaa2 Tx queue and channel mapping 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta 2026-09-15 12:01 ` [PATCH v3-S3 01/10] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 03/10] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta ` (8 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Allocate TX queues based on dpni attribute and align the bounds check with the RX queue logic: - compute nb_tx_queues from num_tx_tcs * num_queues (respecting DPNI_OPT_SINGLE_SENDER) and cap at MAX_TX_QUEUES (128) - cap nb_rx_queues at MAX_RX_QUEUES (128) - cap num_channels at DPAA2_MAX_CHANNELS - assign tc_index/flow_id at queue-allocation time instead of at queue-setup time - replace the open-coded (channel << 8 | tc) with DPNI_BUILD_PARAM(channel, tc) throughout tx_queue_setup - initialize fqid to DPAA2_INVALID_FQ_ID and use it as the already-configured guard (replacing DPAA2_INVALID_FLOW_ID) - add a per-device tx_channels[] array for channel mapping Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/dpaa2_ethdev.c | 125 +++++++++++++++--------- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +- 3 files changed, 84 insertions(+), 47 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index ef65e7895a..f0bc9a3063 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -82,6 +82,7 @@ #define DPAA2_DPCI_MAX_QUEUES 2 #define DPAA2_INVALID_FLOW_ID 0xffff +#define DPAA2_INVALID_FQ_ID ((uint32_t)(-1)) #define DPAA2_INVALID_CGID 0xff #define SEC_FLC_DHR_OUTBOUND (-114) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 4be804a995..fd10827dc4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -518,17 +518,13 @@ static int dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint16_t dist_idx; - uint32_t vq_id; - uint8_t num_rxqueue_per_tc; - struct dpaa2_queue *mc_q, *mcq; + uint8_t num_queue_per_tc; + struct dpaa2_queue *mc_q, *dpaa2_q; uint32_t tot_queues; int i, ret = 0; - struct dpaa2_queue *dpaa2_q; PMD_INIT_FUNC_TRACE(); - num_rxqueue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); if (priv->flags & DPAA2_TX_CONF_ENABLE) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else @@ -540,8 +536,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) return -ENOBUFS; } + num_queue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); for (i = 0; i < priv->nb_rx_queues; i++) { mc_q->eth_data = dev->data; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->rx_vq[i] = mc_q++; dpaa2_q = priv->rx_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -565,9 +565,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } + num_queue_per_tc = (priv->nb_tx_queues / priv->num_tx_tc); for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->flow_id = DPAA2_INVALID_FLOW_ID; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_vq[i] = mc_q++; dpaa2_q = (struct dpaa2_queue *)priv->tx_vq[i]; dpaa2_q->cscn = rte_malloc(NULL, @@ -582,8 +585,9 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->tc_index = i; - mc_q->flow_id = 0; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_conf_vq[i] = mc_q++; dpaa2_q = priv->tx_conf_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -593,14 +597,6 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - vq_id = 0; - for (dist_idx = 0; dist_idx < priv->nb_rx_queues; dist_idx++) { - mcq = priv->rx_vq[vq_id]; - mcq->tc_index = dist_idx / num_rxqueue_per_tc; - mcq->flow_id = dist_idx % num_rxqueue_per_tc; - vq_id++; - } - return 0; fail_tx_conf: i -= 1; @@ -976,6 +972,12 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, return ret; } dpaa2_q = priv->rx_vq[rx_queue_id]; + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", + dev->data->name, rx_queue_id); + dev->data->rx_queues[rx_queue_id] = dpaa2_q; + return 0; + } dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1164,7 +1166,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->offloads = tx_conf->offloads; /* Return if queue already configured */ - if (dpaa2_q->flow_id != DPAA2_INVALID_FLOW_ID) { + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: TXQ[%d] has been setup", + dev->data->name, tx_queue_id); dev->data->tx_queues[tx_queue_id] = dpaa2_q; return 0; } @@ -1172,26 +1176,24 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - tc_id = tx_queue_id % priv->num_tx_tc; - channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; - flow_id = 0; + tc_id = dpaa2_q->tc_index; + flow_id = dpaa2_q->flow_id; + if (tc_id < priv->num_channels) + channel_id = priv->tx_channels[tc_id]; + else + channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); if (ret) { - DPAA2_PMD_ERR("Error in setting the tx flow: " - "tc_id=%d, flow=%d err=%d", - tc_id, flow_id, ret); - return ret; + DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", + ret, dev->data->name, tc_id, flow_id); + return ret; } - dpaa2_q->flow_id = flow_id; - - dpaa2_q->tc_index = tc_id; - ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, ((channel_id << 8) | dpaa2_q->tc_index), - dpaa2_q->flow_id, &tx_flow_cfg, &qid); + DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1230,10 +1232,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_set_congestion_notification(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), &cong_notif_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), &cong_notif_cfg); if (ret) { - DPAA2_PMD_ERR("Set TX congestion notification err=%d", - ret); + DPAA2_PMD_ERR("Set TX congestion notification err=%d", ret); return ret; } } @@ -1241,31 +1242,32 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dev->data->tx_queues[tx_queue_id] = dpaa2_q; if (priv->flags & DPAA2_TX_CONF_ENABLE) { + tc_id = dpaa2_tx_conf_q->tc_index; + flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; options = options | DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, - options, &tx_conf_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, options, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", - dpaa2_tx_conf_q->tc_index, - dpaa2_tx_conf_q->flow_id, ret); + tc_id, flow_id, ret); return ret; } ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, &tx_conf_cfg, &qid); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_conf_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; } dpaa2_tx_conf_q->fqid = qid.fqid; } + return 0; } @@ -1324,6 +1326,8 @@ dpaa2_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id) /* keep the DPCON on the FQ across a reconfigure; freed at dev_close */ if (dpaa2_q->napi_dpcon) dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); + + dpaa2_q->fqid = DPAA2_INVALID_FQ_ID; } static int @@ -3556,10 +3560,41 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; - for (i = 0; i < attr.num_rx_tcs; i++) - priv->nb_rx_queues += attr.num_queues; + { + uint32_t num_rxqueue_per_tc = attr.num_queues; + uint32_t max_rxqueue_per_tc = MAX_RX_QUEUES / attr.num_rx_tcs; - priv->nb_tx_queues = attr.num_tx_tcs * attr.num_channels; + if (num_rxqueue_per_tc > max_rxqueue_per_tc) { + DPAA2_PMD_WARN("Too many RXQs per TC(%u) > %u, reduce it to %u", + num_rxqueue_per_tc, max_rxqueue_per_tc, + max_rxqueue_per_tc); + num_rxqueue_per_tc = max_rxqueue_per_tc; + } + priv->nb_rx_queues = attr.num_rx_tcs * num_rxqueue_per_tc; + } + { + uint32_t num_txqueue_per_tc; + uint32_t max_txqueue_per_tc = MAX_TX_QUEUES / attr.num_tx_tcs; + + if (attr.options & DPNI_OPT_SINGLE_SENDER) + num_txqueue_per_tc = 1; + else + num_txqueue_per_tc = attr.num_queues; + if (num_txqueue_per_tc > max_txqueue_per_tc) { + DPAA2_PMD_WARN("Too many TXQs per TC(%u) > %u, reduce it to %u", + num_txqueue_per_tc, max_txqueue_per_tc, + max_txqueue_per_tc); + num_txqueue_per_tc = max_txqueue_per_tc; + } + priv->nb_tx_queues = attr.num_tx_tcs * num_txqueue_per_tc; + } + if (priv->num_channels > DPAA2_MAX_CHANNELS) { + DPAA2_PMD_WARN("Too many TX channels(%d) > %d, reduce it to %d", + priv->num_channels, DPAA2_MAX_CHANNELS, DPAA2_MAX_CHANNELS); + priv->num_channels = DPAA2_MAX_CHANNELS; + } + for (i = 0; i < priv->num_channels; i++) + priv->tx_channels[i] = i; DPAA2_PMD_DEBUG("RX-TC= %d, rx_queues= %d, tx_queues=%d, max_cgs=%d", priv->num_rx_tc, priv->nb_rx_queues, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 3ed7ab50a3..f55b3ce5dd 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -30,7 +30,7 @@ #define MAX_TCS DPNI_MAX_TC #define MAX_RX_QUEUES 128 -#define MAX_TX_QUEUES 16 +#define MAX_TX_QUEUES 128 #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 @@ -457,13 +457,14 @@ struct dpaa2_dev_priv { int32_t hw_id; int32_t qdid; uint16_t token; + uint16_t tx_channels[DPAA2_MAX_CHANNELS]; uint8_t nb_tx_queues; uint8_t nb_rx_queues; uint32_t options; void *rx_vq[MAX_RX_QUEUES]; void *tx_vq[MAX_TX_QUEUES]; struct dpaa2_bp_list *bp_list; /**<Attached buffer pool list */ - void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; + void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ int psr_dynfield_offset; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 03/10] drivers: refresh dpaa2 MC and SoC version info 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta 2026-09-15 12:01 ` [PATCH v3-S3 01/10] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 02/10] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-17 6:51 ` David Marchand 2026-09-15 12:02 ` [PATCH v3-S3 04/10] drivers: identify dpaa2 soft parser protocol Prashant Gupta ` (7 subsequent siblings) 10 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Fix MC revision typo to correct major to minor. Get MC/SoC rev info only once and save them in bus info as well as other information to reduce replicated variables. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 12 +- drivers/bus/fslmc/fslmc_bus.c | 2 + drivers/bus/fslmc/fslmc_vfio.c | 193 ++++++++++++++++++----- drivers/bus/fslmc/fslmc_vfio.h | 30 +++- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 79 +--------- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 7 - drivers/bus/fslmc/private.h | 3 + drivers/net/dpaa2/dpaa2_ethdev.c | 18 +-- drivers/net/dpaa2/dpaa2_ethdev.h | 1 + drivers/net/dpaa2/dpaa2_rxtx.c | 10 +- 10 files changed, 219 insertions(+), 136 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 44f81cf662..b4a5a86318 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2021-2023 NXP + * Copyright 2016,2021-2026 NXP * */ @@ -89,6 +89,14 @@ enum rte_dpaa2_dev_type { DPAA2_DEVTYPE_MAX, }; +struct rte_fslmc_bus_info { + void *mem_pool; + int sp_protocol; + uint64_t mc_rev; + uint32_t svr; + uint32_t pvr; +}; + /** * A structure describing a DPAA2 device. */ @@ -102,6 +110,8 @@ struct rte_dpaa2_device { char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ + struct rte_dma_dev *dmadev; /**< DMA device */ + const struct rte_fslmc_bus_info *bus_info; }; typedef int (*rte_dpaa2_obj_create_t)(int vdev_fd, diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index ee162b0ed8..2427421075 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -29,6 +29,7 @@ struct rte_bus rte_fslmc_bus; static int fslmc_bus_device_count[DPAA2_DEVTYPE_MAX]; +struct rte_fslmc_bus_info fslmc_bus_info; #define DPAA2_SEQN_DYNFIELD_NAME "dpaa2_seqn_dynfield" RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) @@ -199,6 +200,7 @@ scan_one_fslmc_device(char *dev_name) goto cleanup; } dev->device.devargs = rte_bus_find_devargs(&rte_fslmc_bus, dev_name); + dev->bus_info = &fslmc_bus_info; /* Update the device found into the device_count table */ fslmc_bus_device_count[dev->dev_type]++; diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index adde629ce6..5ccb457a75 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -87,6 +87,83 @@ enum { FSLMC_VFIO_SOCKET_REQ_MEM }; +/* Variable to store DPAA2 platform type */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) +uint32_t dpaa2_svr_family; + +/* Variable to store DPAA2 DQRR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) +uint32_t dpaa2_dqrr_size; +/* Variable to store DPAA2 EQCR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) +uint32_t dpaa2_eqcr_size; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_base) +uint32_t dpaa2_cluster_base; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_size) +uint32_t dpaa2_cluster_size; + +struct fslmc_soc_type { + uint32_t svr; + uint32_t cluster_base; + uint32_t cluster_size; + uint32_t qm_dq_size; + uint32_t qm_eq_size; +}; + +/* For LS208X platform There are four clusters with following mapping: + * Cluster 1 (ID = x04) : CPU0, CPU1; + * Cluster 2 (ID = x05) : CPU2, CPU3; + * Cluster 3 (ID = x06) : CPU4, CPU5; + * Cluster 4 (ID = x07) : CPU6, CPU7; + */ +/* For LS108X platform There are two clusters with following mapping: + * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; + * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; + */ +/* For LX2160 platform There are four clusters with following mapping: + * Cluster 1 (ID = x00) : CPU0, CPU1; + * Cluster 2 (ID = x01) : CPU2, CPU3; + * Cluster 3 (ID = x02) : CPU4, CPU5; + * Cluster 4 (ID = x03) : CPU6, CPU7; + * Cluster 1 (ID = x04) : CPU8, CPU9; + * Cluster 2 (ID = x05) : CPU10, CP11; + * Cluster 3 (ID = x06) : CPU12, CPU13; + * Cluster 4 (ID = x07) : CPU14, CPU15; + */ + +int +fslmc_vfio_core_cluster_sdest(uint32_t cpu_id) +{ + int x = cpu_id / dpaa2_cluster_size; + + if (!dpaa2_cluster_size) { + DPAA2_BUS_ERR("SoC type has not been initialized!"); + + return -ENODEV; + } + + return dpaa2_cluster_base + x; +} + +static const struct fslmc_soc_type s_soc_type[] = { + { + SVR_LS2080A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS2088A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS1080A, 2, 4, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LX2160A, 0, 2, + DPAA2_LX2_DQRR_RING_SIZE, DPAA2_LX2_EQCR_RING_SIZE + } +}; + RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_get_mcp_ptr) void * dpaa2_get_mcp_ptr(int portal_idx) @@ -168,6 +245,63 @@ rte_fslmc_object_register(struct rte_dpaa2_object *object) TAILQ_INSERT_TAIL(&dpaa2_obj_list, object, next); } +static int +fslmc_vfio_get_bus_info(void *regs, struct rte_fslmc_bus_info *bus_info) +{ + struct fsl_mc_io mc_io; + struct mc_version mc_ver_info = {0}; + struct mc_soc_version mc_plat_info; + int ret; + size_t i; + + mc_io.regs = regs; + + ret = mc_get_version(&mc_io, CMD_PRI_LOW, &mc_ver_info); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to obtain MC version.", ret); + return ret; + } + DPAA2_BUS_INFO("MC version is %d.%d.%d.", mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + bus_info->mc_rev = RTE_FSL_MC_REV(mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + if (bus_info->mc_rev < RTE_FSL_MC_REV(MC_VER_MAJOR, MC_VER_MINOR, 0)) { + DPAA2_BUS_ERR("DPAA2 MC version not compatible! %d.%d.%d < %d.%d.0", + mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, + MC_VER_MAJOR, MC_VER_MINOR); + return -EPERM; + } + + memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); + ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); + if (ret) { + DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); + return ret; + } + + for (i = 0; i < RTE_DIM(s_soc_type); i++) { + if ((mc_plat_info.svr & DPAA2_SVR_MASK) == s_soc_type[i].svr) { + dpaa2_svr_family = s_soc_type[i].svr; + dpaa2_cluster_base = s_soc_type[i].cluster_base; + dpaa2_cluster_size = s_soc_type[i].cluster_size; + dpaa2_dqrr_size = s_soc_type[i].qm_dq_size; + dpaa2_eqcr_size = s_soc_type[i].qm_eq_size; + break; + } + } + if (i == RTE_DIM(s_soc_type)) { + DPAA2_BUS_ERR("Invalid SoC version: 0x%08x", mc_plat_info.svr); + return -ENODEV; + } + + bus_info->svr = mc_plat_info.svr; + bus_info->pvr = mc_plat_info.pvr; + + return 0; +} + static const char * fslmc_vfio_get_group_name(void) { @@ -1246,9 +1380,9 @@ fslmc_vfio_setup_device(const char *dev_addr, dev_addr); } -static intptr_t vfio_map_mcp_obj(const char *mcp_obj) +static void *fslmc_vfio_map_mcp_obj(const char *mcp_obj) { - intptr_t v_addr = (intptr_t)MAP_FAILED; + void *v_addr = MAP_FAILED; int32_t ret, mc_fd; struct vfio_group_status status = { .argsz = sizeof(status) }; @@ -1264,7 +1398,7 @@ static intptr_t vfio_map_mcp_obj(const char *mcp_obj) goto MC_FAILURE; } - v_addr = (size_t)mmap(NULL, reg_info.size, + v_addr = mmap(NULL, reg_info.size, PROT_WRITE | PROT_READ, MAP_SHARED, mc_fd, reg_info.offset); @@ -1387,7 +1521,7 @@ rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, } static void -fslmc_close_iodevices(struct rte_dpaa2_device *dev, +fslmc_vfio_close_iodevices(struct rte_dpaa2_device *dev, int vfio_fd) { struct rte_dpaa2_object *object = NULL; @@ -1430,11 +1564,11 @@ fslmc_close_iodevices(struct rte_dpaa2_device *dev, } /* - * fslmc_process_iodevices for processing only IO (ETH, CRYPTO, and possibly + * fslmc_vfio_process_iodevices for processing only IO (ETH, CRYPTO, and possibly * EVENT) devices. */ static int -fslmc_process_iodevices(struct rte_dpaa2_device *dev) +fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev) { int dev_fd, ret; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; @@ -1476,12 +1610,10 @@ fslmc_process_iodevices(struct rte_dpaa2_device *dev) } static int -fslmc_process_mcp(struct rte_dpaa2_device *dev) +fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev) { int ret; - intptr_t v_addr; - struct fsl_mc_io dpmng = {0}; - struct mc_version mc_ver_info = {0}; + void *v_addr; rte_mcp_ptr_list = malloc(sizeof(void *) * (MC_PORTAL_INDEX + 1)); if (!rte_mcp_ptr_list) { @@ -1490,15 +1622,16 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) goto cleanup; } - v_addr = vfio_map_mcp_obj(dev->device.name); - if (v_addr == (intptr_t)MAP_FAILED) { + v_addr = fslmc_vfio_map_mcp_obj(dev->device.name); + if (v_addr == MAP_FAILED) { DPAA2_BUS_ERR("Error mapping region (errno = %d)", errno); ret = -1; goto cleanup; } - /* check the MC version compatibility */ - dpmng.regs = (void *)v_addr; + ret = fslmc_vfio_get_bus_info(v_addr, &fslmc_bus_info); + if (ret) + goto cleanup; /* In case of secondary processes, MC version check is no longer * required. @@ -1508,23 +1641,7 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) return 0; } - if (mc_get_version(&dpmng, CMD_PRI_LOW, &mc_ver_info)) { - DPAA2_BUS_ERR("Unable to obtain MC version"); - ret = -1; - goto cleanup; - } - - if ((mc_ver_info.major != MC_VER_MAJOR) || - (mc_ver_info.minor < MC_VER_MINOR)) { - DPAA2_BUS_ERR("DPAA2 MC version not compatible!" - " Expected %d.%d.x, Detected %d.%d.%d", - MC_VER_MAJOR, MC_VER_MINOR, - mc_ver_info.major, mc_ver_info.minor, - mc_ver_info.revision); - ret = -1; - goto cleanup; - } - rte_mcp_ptr_list[MC_PORTAL_INDEX] = (void *)v_addr; + rte_mcp_ptr_list[MC_PORTAL_INDEX] = v_addr; return 0; @@ -1566,7 +1683,7 @@ fslmc_vfio_close_group(void) case DPAA2_CRYPTO: case DPAA2_QDMA: case DPAA2_IO: - fslmc_close_iodevices(dev, vfio_group_fd); + fslmc_vfio_close_iodevices(dev, vfio_group_fd); break; case DPAA2_CON: case DPAA2_CI: @@ -1575,7 +1692,7 @@ fslmc_vfio_close_group(void) if (rte_eal_process_type() == RTE_PROC_SECONDARY) continue; - fslmc_close_iodevices(dev, vfio_group_fd); + fslmc_vfio_close_iodevices(dev, vfio_group_fd); break; case DPAA2_DPRTC: default: @@ -1638,7 +1755,7 @@ fslmc_vfio_process_group(void) } if (!found_mportal) { - ret = fslmc_process_mcp(dev); + ret = fslmc_vfio_process_mcp(dev); if (ret) { DPAA2_BUS_ERR("Unable to map MC Portal"); return ret; @@ -1667,7 +1784,7 @@ fslmc_vfio_process_group(void) current_device = 0; RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { if (dev->dev_type == DPAA2_DPRC) { - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_ERR("Unable to process dprc"); return ret; @@ -1699,7 +1816,7 @@ fslmc_vfio_process_group(void) case DPAA2_ETH: case DPAA2_CRYPTO: case DPAA2_QDMA: - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); @@ -1722,7 +1839,7 @@ fslmc_vfio_process_group(void) /* Call the object creation routine and remove the * device entry from device list */ - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); @@ -1746,7 +1863,7 @@ fslmc_vfio_process_group(void) } } - ret = fslmc_process_iodevices(dev); + ret = fslmc_vfio_process_iodevices(dev); if (ret) { DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h index c995fd67b8..554123ffa6 100644 --- a/drivers/bus/fslmc/fslmc_vfio.h +++ b/drivers/bus/fslmc/fslmc_vfio.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019-2023 NXP + * Copyright 2016,2019-2026 NXP * */ @@ -9,6 +9,8 @@ #define _FSLMC_VFIO_H_ #include <rte_compat.h> +#include <rte_vfio.h> +#include <rte_interrupts.h> /* Pathname of FSL-MC devices directory. */ #define SYSFS_FSL_MC_DEVICES "/sys/bus/fsl-mc/devices" @@ -44,6 +46,30 @@ struct fslmc_vfio_container { extern char *fslmc_container; +extern uint32_t dpaa2_svr_family; +extern uint32_t dpaa2_dqrr_size; +extern uint32_t dpaa2_eqcr_size; +extern uint32_t dpaa2_cluster_base; +extern uint32_t dpaa2_cluster_size; + +#define DPAA2_SVR_MASK 0xffff0000 + +#define SVR_LS1080A 0x87030000 +#define SVR_LS2080A 0x87010000 +#define SVR_LS2088A 0x87090000 +#define SVR_LX2160A 0x87360000 + +#define MC_MAJOR_OFFSET 32 +#define MC_MINOR_OFFSET 16 +#define MC_MINOR_MASK ((((uint64_t)1) << (MC_MAJOR_OFFSET - MC_MINOR_OFFSET)) - 1) +#define MC_REVISION_MASK ((((uint64_t)1) << MC_MINOR_OFFSET) - 1) +#define RTE_FSL_MC_REV(major, minor, revision) \ + ((((uint64_t)(major)) << MC_MAJOR_OFFSET) + \ + (((uint64_t)(minor)) << MC_MINOR_OFFSET) + (revision)) +#define RTE_FSL_MC_REV_MAJOR(rev) ((uint32_t)((rev) >> MC_MAJOR_OFFSET)) +#define RTE_FSL_MC_REV_MINOR(rev) ((uint32_t)(((rev) >> MC_MINOR_OFFSET) & MC_MINOR_MASK)) +#define RTE_FSL_MC_REV_REVISION(rev) ((uint32_t)((rev) & MC_REVISION_MASK)) + __rte_internal int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index); @@ -60,4 +86,6 @@ int fslmc_vfio_close_group(void); char *fslmc_get_container(void); int fslmc_get_container_group(const char *group_name, int *gropuid); int fslmc_vfio_dmamap(void); +int fslmc_vfio_core_cluster_sdest(uint32_t cpu_id); + #endif /* _FSLMC_VFIO_H_ */ diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index e17050b625..20d1bb2a66 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2022 NXP + * Copyright 2016-2026 NXP * */ #include <uapi/linux/vfio.h> @@ -63,45 +63,9 @@ static struct dpio_dev_list dpio_dev_list = TAILQ_HEAD_INITIALIZER(dpio_dev_list); /*!< DPIO device list */ static uint32_t io_space_count; -/* Variable to store DPAA2 platform type */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) -uint32_t dpaa2_svr_family; - -/* Variable to store DPAA2 DQRR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) -uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) -uint8_t dpaa2_eqcr_size; - /* Variable to hold the portal_key, once created.*/ static pthread_key_t dpaa2_portal_key; -/*Stashing Macros default for LS208x*/ -static int dpaa2_core_cluster_base = 0x04; -static int dpaa2_cluster_sz = 2; - -/* For LS208X platform There are four clusters with following mapping: - * Cluster 1 (ID = x04) : CPU0, CPU1; - * Cluster 2 (ID = x05) : CPU2, CPU3; - * Cluster 3 (ID = x06) : CPU4, CPU5; - * Cluster 4 (ID = x07) : CPU6, CPU7; - */ -/* For LS108X platform There are two clusters with following mapping: - * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; - * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; - */ -/* For LX2160 platform There are four clusters with following mapping: - * Cluster 1 (ID = x00) : CPU0, CPU1; - * Cluster 2 (ID = x01) : CPU2, CPU3; - * Cluster 3 (ID = x02) : CPU4, CPU5; - * Cluster 4 (ID = x03) : CPU6, CPU7; - * Cluster 1 (ID = x04) : CPU8, CPU9; - * Cluster 2 (ID = x05) : CPU10, CP11; - * Cluster 3 (ID = x06) : CPU12, CPU13; - * Cluster 4 (ID = x07) : CPU14, CPU15; - */ - static struct dpaa2_dpio_dev *get_dpio_dev_from_id(int32_t dpio_id) { struct dpaa2_dpio_dev *dpio_dev = NULL; @@ -141,14 +105,6 @@ dpaa2_get_core_id(void) return cpu_id; } -static int -dpaa2_core_cluster_sdest(int cpu_id) -{ - int x = cpu_id / dpaa2_cluster_sz; - - return dpaa2_core_cluster_base + x; -} - static void dpaa2_affine_dpio_intr_to_respective_core(int32_t dpio_id, int cpu_id) { @@ -307,15 +263,17 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx /* Set the STASH Destination depending on Current CPU ID. * Valid values of SDEST are 4,5,6,7. Where, */ - sdest = dpaa2_core_cluster_sdest(cpu_id); + sdest = fslmc_vfio_core_cluster_sdest(cpu_id); DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", dpio_dev->index, cpu_id, sdest); + if (sdest < 0) + return sdest; ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token, sdest); if (ret) { DPAA2_BUS_ERR("%d ERROR in SDEST", ret); - return -1; + return ret; } #ifdef RTE_EVENT_DPAA2 @@ -542,33 +500,6 @@ dpaa2_create_dpio_device(int vdev_fd, goto err; } - /* find the SoC type for the first time */ - if (!dpaa2_svr_family) { - struct mc_soc_version mc_plat_info = {0}; - - if (mc_get_soc_version(dpio_dev->dpio, - CMD_PRI_LOW, &mc_plat_info)) { - DPAA2_BUS_ERR("Unable to get SoC version information"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LS1080A) { - dpaa2_core_cluster_base = 0x02; - dpaa2_cluster_sz = 4; - DPAA2_BUS_DEBUG("LS108x (A53) Platform Detected"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LX2160A) { - dpaa2_core_cluster_base = 0x00; - dpaa2_cluster_sz = 2; - DPAA2_BUS_DEBUG("LX2160 Platform Detected"); - } - dpaa2_svr_family = (mc_plat_info.svr & 0xffff0000); - - if (dpaa2_svr_family == SVR_LX2160A) { - dpaa2_dqrr_size = DPAA2_LX2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_LX2_EQCR_RING_SIZE; - } else { - dpaa2_dqrr_size = DPAA2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_EQCR_RING_SIZE; - } - } - if (dpaa2_svr_family == SVR_LX2160A) reg_info.index = DPAA2_SWP_CENA_MEM_REGION; else diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 7e2271cc35..2c559e5354 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -35,13 +35,6 @@ RTE_DECLARE_PER_LCORE(struct dpaa2_io_portal_t, _dpaa2_io); #define DPAA2_PER_LCORE_DQRR_MBUF(i) \ RTE_PER_LCORE(_dpaa2_io).dpio_dev->dpaa2_held_bufs.mbuf[i] -/* Variable to store DPAA2 DQRR size */ -extern uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -extern uint8_t dpaa2_eqcr_size; - -extern struct dpaa2_io_portal_t dpaa2_io_portal[RTE_MAX_LCORE]; - /* Affine a DPIO portal to current processing thread */ __rte_internal int dpaa2_affine_qbman_swp(void); diff --git a/drivers/bus/fslmc/private.h b/drivers/bus/fslmc/private.h index 20a454c3fc..1c8a3e59e9 100644 --- a/drivers/bus/fslmc/private.h +++ b/drivers/bus/fslmc/private.h @@ -11,4 +11,7 @@ extern struct rte_bus rte_fslmc_bus; +/* MC/SoC version and capability info, shared by the bus and VFIO code. */ +extern struct rte_fslmc_bus_info fslmc_bus_info; + #endif /* BUS_FSLMC_PRIVATE_H */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index fd10827dc4..d3ca0e291b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -329,24 +329,21 @@ dpaa2_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size) { int ret; + uint32_t major, minor, rev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = dev->process_private; struct mc_soc_version mc_plat_info = {0}; - struct mc_version mc_ver_info = {0}; PMD_INIT_FUNC_TRACE(); + major = RTE_FSL_MC_REV_MAJOR(priv->mc_rev); + minor = RTE_FSL_MC_REV_MINOR(priv->mc_rev); + rev = RTE_FSL_MC_REV_REVISION(priv->mc_rev); if (mc_get_soc_version(dpni, CMD_PRI_LOW, &mc_plat_info)) DPAA2_PMD_WARN("\tmc_get_soc_version failed"); - if (mc_get_version(dpni, CMD_PRI_LOW, &mc_ver_info)) - DPAA2_PMD_WARN("\tmc_get_version failed"); - - ret = snprintf(fw_version, fw_size, - "%x-%d.%d.%d", - mc_plat_info.svr, - mc_ver_info.major, - mc_ver_info.minor, - mc_ver_info.revision); + ret = snprintf(fw_version, fw_size, "%x-%d.%d.%d", + mc_plat_info.svr, major, minor, rev); if (ret < 0) return -EINVAL; @@ -3539,6 +3536,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + priv->mc_rev = dpaa2_dev->bus_info->mc_rev; priv->num_rx_tc = attr.num_rx_tcs; priv->num_tx_tc = attr.num_tx_tcs; priv->qos_entries = attr.qos_entries; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index f55b3ce5dd..33bbd666c9 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -529,6 +529,7 @@ struct dpaa2_dev_priv { uint32_t *cnt_idx_dma_mem; uint64_t *cnt_values_dma_mem; uint64_t cnt_idx_iova, cnt_values_iova; + uint64_t mc_rev; struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index d07db3869a..48f5fb7288 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1123,9 +1123,9 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, /* Function receive frames for a given device and VQ */ struct dpaa2_queue *dpaa2_q = queue; struct qbman_result *dq_storage; - uint32_t fqid = dpaa2_q->fqid; - int ret, num_rx = 0, next_pull = nb_pkts, num_pulled; - uint8_t pending, status; + uint32_t fqid = dpaa2_q->fqid, next_pull = nb_pkts; + int ret; + uint8_t pending, status, num_rx = 0, num_pulled; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; @@ -1269,8 +1269,8 @@ uint16_t dpaa2_dev_tx_conf(void *queue) struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; struct qbman_result *dq_storage; uint32_t fqid = dpaa2_q->fqid; - int ret, num_tx_conf = 0, num_pulled; - uint8_t pending, status; + int ret, num_tx_conf = 0; + uint8_t pending, status, num_pulled; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v3-S3 03/10] drivers: refresh dpaa2 MC and SoC version info 2026-09-15 12:02 ` [PATCH v3-S3 03/10] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta @ 2026-09-17 6:51 ` David Marchand 0 siblings, 0 replies; 356+ messages in thread From: David Marchand @ 2026-09-17 6:51 UTC (permalink / raw) To: Prashant Gupta, Hemant Agrawal, Jun Yang; +Cc: stephen, dev On Tue, 15 Sept 2026 at 14:02, Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > @@ -102,6 +110,8 @@ struct rte_dpaa2_device { > char ep_name[RTE_DEV_NAME_MAX_LEN]; > struct rte_intr_handle *intr_handle; /**< Interrupt handle */ > char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ > + struct rte_dma_dev *dmadev; /**< DMA device */ > + const struct rte_fslmc_bus_info *bus_info; > }; No dmadev back reference in the bus device object. Thanks. -- David Marchand ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v3-S3 04/10] drivers: identify dpaa2 soft parser protocol 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (2 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 03/10] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 05/10] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta ` (6 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Identify if soft parser protocol firmware is loaded by checking firmware magic number. Enable flow/parser of ECPRI, GENEVE, ROCEv2 and VXLAN's spec only with soft parser protocol firmware being loaded. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/fslmc_bus.c | 91 +++++++++++++++++++++- drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_flow.c | 129 ++++++++----------------------- drivers/net/dpaa2/dpaa2_rxtx.c | 10 +++ 4 files changed, 134 insertions(+), 98 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index 2427421075..c3415bc541 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2018-2021 NXP + * Copyright 2016,2018-2026 NXP * */ @@ -8,6 +8,7 @@ #include <dirent.h> #include <stdalign.h> #include <stdbool.h> +#include <sys/mman.h> #include <eal_export.h> #include <rte_log.h> @@ -35,6 +36,93 @@ struct rte_fslmc_bus_info fslmc_bus_info; RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) int dpaa2_seqn_dynfield_offset = -1; +/** For LX2160A, LS2088A and LS1088A*/ +#define WRIOP_CCSR_BASE 0x8b80000 +#define WRIOP_CCSR_CTLU_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 + +#define WRIOP_INGRESS_PARSER_PHY \ + (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) + +struct __rte_packed_begin dpaa2_parser_ccsr { + uint32_t psr_cfg; + uint32_t psr_idle; + uint32_t psr_pclm; + uint8_t psr_ver_min; + uint8_t psr_ver_maj; + uint8_t psr_id1_l; + uint8_t psr_id1_h; + uint32_t psr_rev2; + uint8_t rsv[0x2c]; + uint8_t sp_ins[4032]; +} __rte_packed_end; + +#define SP_PROTOCOL_MAGIC_DATA 0xabcd +#define SP_PROTOCOL_MAGIC_OFFSET 0x4 + +/** Number of soft parser firmware bytes reported for debugging. */ +#define SP_PRINT_LEN 128 +/** Firmware bytes logged per debug line. */ +#define SP_DUMP_BYTES_PER_LINE 16 + +static void +fslmc_soft_parser_protocol_supported(void) +{ + int fd, i, pos = 0; + void *map_addr = NULL; + const struct dpaa2_parser_ccsr *parser_ccsr = NULL; + const uint16_t *magic_num; + char line[SP_DUMP_BYTES_PER_LINE * 3 + 1]; + + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd < 0) { + DPAA2_BUS_ERR("open \"/dev/mem\" ERROR(%d)", fd); + goto exit; + } + + map_addr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, + WRIOP_INGRESS_PARSER_PHY); + parser_ccsr = map_addr; + if (!parser_ccsr) { + DPAA2_BUS_ERR("Map 0x%" PRIx64 "(size=0x%zx) failed", + (uint64_t)WRIOP_INGRESS_PARSER_PHY, + sizeof(struct dpaa2_parser_ccsr)); + goto exit; + } + + DPAA2_BUS_DEBUG("Soft ParserID:0x%02x%02x, Rev:maj(%02x), min(%02x)", + parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, + parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); + + magic_num = (const void *)&parser_ccsr->sp_ins[SP_PROTOCOL_MAGIC_OFFSET]; + if (*magic_num == SP_PROTOCOL_MAGIC_DATA) { + fslmc_bus_info.sp_protocol = true; + DPAA2_BUS_INFO("Soft parser protocol support."); + DPAA2_BUS_DEBUG("First %d bytes of sp protocol firmware:", + SP_PRINT_LEN); + for (i = 0; i < SP_PRINT_LEN; i++) { + pos += snprintf(&line[pos], sizeof(line) - pos, + "%02x ", parser_ccsr->sp_ins[i]); + if ((i + 1) % SP_DUMP_BYTES_PER_LINE == 0) { + DPAA2_BUS_DEBUG("%s", line); + pos = 0; + } + } + if (pos) + DPAA2_BUS_DEBUG("%s", line); + } + +exit: + if (map_addr) + munmap(map_addr, sizeof(struct dpaa2_parser_ccsr)); + if (fd >= 0) + close(fd); +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_get_device_count) uint32_t rte_fslmc_get_device_count(enum rte_dpaa2_dev_type device_type) @@ -345,6 +433,7 @@ rte_fslmc_scan(void) DPAA2_BUS_ERR("Unable to open VFIO group directory"); goto scan_fail; } + fslmc_soft_parser_protocol_supported(); /* Scan the DPRC container object */ ret = scan_one_fslmc_device(group_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index d3ca0e291b..889084c4ce 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3751,6 +3751,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; + priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; + DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2662c358e4..cde2f5a9d3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -9,7 +9,6 @@ #include <string.h> #include <unistd.h> #include <stdarg.h> -#include <sys/mman.h> #include <rte_ethdev.h> #include <rte_log.h> @@ -22,9 +21,9 @@ #include <dpaa2_ethdev.h> #include <dpaa2_pmd_logs.h> +#include "dpaa2_parser_decode.h" static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -434,92 +433,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -3538,6 +3451,11 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); + return -ENOTSUP; + } + ret = dpaa2_flow_extract_support((const uint8_t *)mask, RTE_FLOW_ITEM_TYPE_GRE); if (ret) { @@ -3583,6 +3501,11 @@ dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, struct dpaa2_dev_priv *priv = dev->data->dev_private; const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -3681,6 +3604,11 @@ dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("ROCEV2 flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -4000,6 +3928,11 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); + return -ENOTSUP; + } + group = attr->group; /* Parse pattern list to get the matching parameters */ @@ -4725,7 +4658,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, static int dpaa2_flow_item_convert(const struct rte_flow_item pattern[], - struct rte_dpaa2_flow_item **dpaa2_pattern) + struct rte_dpaa2_flow_item **dpaa2_pattern, int sp_protocol) { struct rte_dpaa2_flow_item *new_pattern; int num = 0, tunnel_start = 0; @@ -4737,7 +4670,7 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], } new_pattern = rte_malloc(NULL, sizeof(struct rte_dpaa2_flow_item) * num, - RTE_CACHE_LINE_SIZE); + RTE_CACHE_LINE_SIZE); if (!new_pattern) { DPAA2_PMD_ERR("Failed to alloc %d flow items", num); return -ENOMEM; @@ -4745,13 +4678,13 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], num = 0; while (pattern[num].type != RTE_FLOW_ITEM_TYPE_END) { - memcpy(&new_pattern[num].generic_item, &pattern[num], - sizeof(struct rte_flow_item)); + rte_memcpy(&new_pattern[num].generic_item, &pattern[num], + sizeof(struct rte_flow_item)); new_pattern[num].in_tunnel = 0; if (pattern[num].type == RTE_FLOW_ITEM_TYPE_VXLAN) tunnel_start = 1; - else if (tunnel_start) + else if (tunnel_start && sp_protocol) new_pattern[num].in_tunnel = 1; num++; } @@ -4788,7 +4721,8 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, if (ret) return ret; - ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern); + ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, + priv->sp_protocol); if (ret) return ret; @@ -5129,7 +5063,8 @@ dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, } static inline int -dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) +dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], + int sp_support) { unsigned int i, j, is_found = 0; int ret = 0; @@ -5153,7 +5088,7 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) } if (is_found) continue; - if (dpaa2_sp_loaded > 0) { + if (sp_support) { for (i = 0; i < sp_supported_num; i++) { if (sp_supported[i] == pattern[j].type) { is_found = 1; @@ -5232,7 +5167,7 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, goto not_valid_params; } /* Verify input pattern list */ - ret = dpaa2_dev_verify_patterns(pattern); + ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol); if (ret < 0) { DPAA2_PMD_ERR("Invalid pattern list is given"); rte_flow_error_set(error, EPERM, diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 48f5fb7288..a03e3fd8db 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -128,6 +128,16 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; } } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 05/10] drivers: assign dpaa2 Rx CGID per traffic class 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (3 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 04/10] drivers: identify dpaa2 soft parser protocol Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 06/10] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta ` (5 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> RXQs in same TC should use same CGID for congestion set. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 3 +- drivers/net/dpaa2/dpaa2_ethdev.c | 252 ++++++++++++------------ drivers/net/dpaa2/dpaa2_ethdev.h | 3 +- 3 files changed, 126 insertions(+), 132 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f0bc9a3063..12216750a8 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -176,7 +176,6 @@ struct __rte_cache_aligned dpaa2_queue { uint32_t fqid; /*!< Unique ID of this queue */ uint16_t flow_id; /*!< To be used by DPAA2 framework */ uint8_t tc_index; /*!< traffic class identifier */ - uint8_t cgid; /*! < Congestion Group id for this queue */ uint64_t rx_pkts; uint64_t tx_pkts; uint64_t err_pkts; @@ -186,6 +185,8 @@ struct __rte_cache_aligned dpaa2_queue { /**Egress*/ struct qbman_result *cscn; }; + void *cfg; + uint8_t options; struct rte_event ev; dpaa2_queue_cb_dqrr_t *cb; dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 889084c4ce..8cd482b538 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP */ #include <time.h> @@ -682,6 +682,9 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) RTE_MAX_LCORE); dpaa2_queue_storage_free(dpaa2_q, RTE_MAX_LCORE); + if (dpaa2_q->cfg) + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; priv->rx_vq[i] = NULL; } /* cleanup tx queue cscn */ @@ -934,11 +937,12 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, struct fsl_mc_io *dpni = dev->process_private; bool dpcon_allocated = false; struct dpaa2_queue *dpaa2_q; - struct dpni_queue cfg; - uint8_t options = 0; - uint8_t flow_id; + struct dpni_queue *cfg; + struct dpni_taildrop taildrop; + uint8_t qopt = 0; + uint16_t flow_id; uint32_t bpid; - int i, ret; + int ret; PMD_INIT_FUNC_TRACE(); @@ -975,6 +979,10 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } + cfg = rte_zmalloc(NULL, sizeof(struct dpni_queue), 0); + if (!cfg) + return -ENOMEM; + dpaa2_q->cfg = cfg; dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1004,125 +1012,101 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, /*Get the flow id from given VQ id*/ flow_id = dpaa2_q->flow_id; - memset(&cfg, 0, sizeof(struct dpni_queue)); + memset(cfg, 0, sizeof(struct dpni_queue)); - options = options | DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_q); + qopt |= DPNI_QUEUE_OPT_USER_CTX; + cfg->user_context = (size_t)(dpaa2_q); /* napi: schedule the FQ to its DPCON once, when the channel is first * grabbed; never re-bound (the MC refuses scheduled->parked at runtime) */ if (dpcon_allocated) { - options |= DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpaa2_q->napi_dpcon->dpcon_id; - } - - /* check if a private cgr available. */ - for (i = 0; i < priv->max_cgs; i++) { - if (!priv->cgid_in_use[i]) { - priv->cgid_in_use[i] = 1; - break; - } + qopt |= DPNI_QUEUE_OPT_DEST; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpaa2_q->napi_dpcon->dpcon_id; } - if (i < priv->max_cgs) { - options |= DPNI_QUEUE_OPT_SET_CGID; - cfg.cgid = i; - dpaa2_q->cgid = cfg.cgid; + /** RXQs in same TC share same cgid.*/ + if (dpaa2_q->tc_index < priv->max_cgs) { + qopt |= DPNI_QUEUE_OPT_SET_CGID; + cfg->cgid = dpaa2_q->tc_index; + priv->cgid_in_use[dpaa2_q->tc_index]++; } else { - dpaa2_q->cgid = DPAA2_INVALID_CGID; + cfg->cgid = DPAA2_INVALID_CGID; } /*if ls2088 or rev2 device, enable the stashing */ if ((dpaa2_svr_family & 0xffff0000) != SVR_LS2080A) { - options |= DPNI_QUEUE_OPT_FLC; - cfg.flc.stash_control = true; - dpaa2_flc_stashing_clear_all(&cfg.flc.value); + qopt |= DPNI_QUEUE_OPT_FLC; + cfg->flc.stash_control = true; + dpaa2_flc_stashing_clear_all(&cfg->flc.value); if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 1; } else { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 0; } if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); } } + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, options, &cfg); + dpaa2_q->tc_index, flow_id, qopt, cfg); if (ret) { + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; DPAA2_PMD_ERR("Error in setting the rx flow: = %d", ret); goto err_free_dpcon; } dpaa2_q->nb_desc = nb_rx_desc; - - if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) { - struct dpni_taildrop taildrop; - + memset(&taildrop, 0, sizeof(struct dpni_taildrop)); + if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) taildrop.enable = 1; - /* Private CGR will use tail drop length as nb_rx_desc. - * for rest cases we can use standard byte based tail drop. - * There is no HW restriction, but number of CGRs are limited, - * hence this restriction is placed. - */ - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - /*enabling per rx queue congestion control */ - taildrop.threshold = nb_rx_desc; - taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; - taildrop.oal = 0; - DPAA2_PMD_DEBUG("Enabling CG Tail Drop on queue = %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - /*enabling per rx queue congestion control */ - taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; - taildrop.units = DPNI_CONGESTION_UNIT_BYTES; - taildrop.oal = CONG_RX_OAL; - DPAA2_PMD_DEBUG("Enabling Byte based Drop on queue= %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, - &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } - } else { /* Disable tail Drop */ - struct dpni_taildrop taildrop = {0}; - DPAA2_PMD_INFO("Tail drop is disabled on queue"); - - taildrop.enable = 0; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } + /* Private CGR will use tail drop length as nb_rx_desc * queues per TC. + * For rest cases we can use standard byte based tail drop. + * There is no HW restriction, but number of CGRs are limited, + * hence this restriction is placed. + */ + if (cfg->cgid != DPAA2_INVALID_CGID && + priv->cgid_in_use[dpaa2_q->tc_index] == 1) { + /*enabling per TC congestion control */ + taildrop.threshold = nb_rx_desc * priv->dist_queues; + taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; + taildrop.oal = 0; + DPAA2_PMD_DEBUG("%s CG Tail Drop on TC%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, + dpaa2_q->tc_index, cfg->cgid, &taildrop); + } else if (cfg->cgid == DPAA2_INVALID_CGID) { + /*enabling per rx queue congestion control */ + taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; + taildrop.units = DPNI_CONGESTION_UNIT_BYTES; + taildrop.oal = CONG_RX_OAL; + DPAA2_PMD_DEBUG("%s Byte based Drop on TC[%d].flow%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index, flow_id); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_QUEUE, DPNI_QUEUE_RX, + dpaa2_q->tc_index, flow_id, &taildrop); + } + if (ret) { + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; + DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", ret); + return ret; } + dpaa2_q->options = qopt; + dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; @@ -1150,8 +1134,8 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct fsl_mc_io *dpni = dev->process_private; struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; - uint8_t options = 0, flow_id; - uint16_t channel_id; + uint8_t qopt = 0; + uint16_t channel_id, flow_id; struct dpni_queue_id qid; uint32_t tc_id; int ret; @@ -1181,7 +1165,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, qopt, &tx_flow_cfg); if (ret) { DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", ret, dev->data->name, tc_id, flow_id); @@ -1190,7 +1174,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, &tx_flow_cfg, &qid); + dpaa2_q->flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1242,12 +1226,12 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; - options = options | DPNI_QUEUE_OPT_USER_CTX; + qopt |= DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, options, &tx_conf_cfg); + flow_id, qopt, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", tc_id, flow_id, ret); @@ -1296,30 +1280,29 @@ dpaa2_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id) struct dpaa2_queue *dpaa2_q = dev->data->rx_queues[rx_queue_id]; struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; struct fsl_mc_io *dpni = priv->eth_dev->process_private; - uint8_t options = 0; + uint8_t qopt = 0; int ret; - struct dpni_queue cfg; + struct dpni_queue *cfg = dpaa2_q->cfg; - memset(&cfg, 0, sizeof(struct dpni_queue)); PMD_INIT_FUNC_TRACE(); total_nb_rx_desc -= dpaa2_q->nb_desc; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - options = DPNI_QUEUE_OPT_CLEAR_CGID; - cfg.cgid = dpaa2_q->cgid; - - ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, dpaa2_q->flow_id, - options, &cfg); - if (ret) - DPAA2_PMD_ERR("Unable to clear CGR from q=%u err=%d", - dpaa2_q->fqid, ret); - priv->cgid_in_use[dpaa2_q->cgid] = 0; - dpaa2_q->cgid = DPAA2_INVALID_CGID; + if (cfg) { + if (cfg->cgid != DPAA2_INVALID_CGID) { + qopt = DPNI_QUEUE_OPT_CLEAR_CGID; + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, + DPNI_QUEUE_RX, dpaa2_q->tc_index, dpaa2_q->flow_id, + qopt, cfg); + if (ret) { + DPAA2_PMD_ERR("Unable to clear CGR from TC[%d].flow%d err=%d", + dpaa2_q->tc_index, dpaa2_q->flow_id, ret); + } + priv->cgid_in_use[cfg->cgid]--; + } + rte_free(cfg); + dpaa2_q->cfg = NULL; } - /* keep the DPCON on the FQ across a reconfigure; freed at dev_close */ if (dpaa2_q->napi_dpcon) dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); @@ -2835,10 +2818,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; + struct dpni_queue *cfg; uint8_t options, priority; int ret; + cfg = dpaa2_ethq->cfg; + if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) dpaa2_ethq->cb = dpaa2_dev_process_parallel_event; else if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) @@ -2851,15 +2836,19 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, priority = (RTE_EVENT_DEV_PRIORITY_LOWEST / queue_conf->ev.priority) * (dpcon->num_priorities - 1); - memset(&cfg, 0, sizeof(struct dpni_queue)); + if (!cfg) { + DPAA2_PMD_ERR("%s: %s-rxq%d was not setup yet!", + __func__, dev->data->name, eth_rx_queue_id); + return -EINVAL; + } options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpcon->dpcon_id; - cfg.destination.priority = priority; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpcon->dpcon_id; + cfg->destination.priority = priority; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) { options |= DPNI_QUEUE_OPT_HOLD_ACTIVE; - cfg.destination.hold_active = 1; + cfg->destination.hold_active = 1; } if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED && @@ -2898,16 +2887,16 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, } options |= DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_ethq); + cfg->user_context = (size_t)(dpaa2_ethq); ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, flow_id, options, cfg); if (ret) { DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); return ret; } - memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); + rte_memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); return 0; } @@ -2919,17 +2908,15 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; - uint8_t options; + struct dpni_queue *cfg; int ret; - memset(&cfg, 0, sizeof(struct dpni_queue)); - options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_NONE; + cfg = dpaa2_ethq->cfg; + cfg->destination.type = DPNI_DEST_NONE; + dpaa2_ethq->options &= ~DPNI_QUEUE_OPT_DEST; ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, dpaa2_ethq->flow_id, dpaa2_ethq->options, cfg); if (ret) DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); @@ -3550,10 +3537,15 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ - if (attr.options & DPNI_OPT_CUSTOM_CG) + if (attr.options & DPNI_OPT_CUSTOM_CG) { priv->max_cgs = attr.num_cgs; - else + if (priv->max_cgs < priv->num_rx_tc) { + DPAA2_PMD_WARN("DPNI%d has no enough cgids(%d) to set %d TCs", + hw_id, priv->max_cgs, priv->num_rx_tc); + } + } else { priv->max_cgs = 0; + } for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 33bbd666c9..6eafa9a9e7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -479,7 +479,8 @@ struct dpaa2_dev_priv { uint8_t en_ordered; uint8_t en_loose_ordered; uint8_t max_cgs; - uint8_t cgid_in_use[MAX_RX_QUEUES]; + /** RXQs in same TC share same cgid.*/ + uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; /* Lowest priority FS flow id to receive flow steering miss frames. */ uint16_t default_flow; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 06/10] drivers: inherit dpaa2 rxq config for event queue 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (4 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 05/10] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-17 6:52 ` David Marchand 2026-09-15 12:02 ` [PATCH v3-S3 07/10] drivers: rework dpaa2 Tx confirmation Prashant Gupta ` (4 subsequent siblings) 10 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The configuration parameter in event queue attachment should use flc and cgid configured in rxq setup. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 2 +- drivers/net/dpaa2/dpaa2_ethdev.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 12216750a8..f87bf51d09 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2025 NXP * */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8cd482b538..77a93ecf91 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -2817,11 +2817,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; + uint8_t flow_id; struct dpni_queue *cfg; uint8_t options, priority; int ret; + flow_id = dpaa2_ethq->flow_id; cfg = dpaa2_ethq->cfg; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v3-S3 06/10] drivers: inherit dpaa2 rxq config for event queue 2026-09-15 12:02 ` [PATCH v3-S3 06/10] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta @ 2026-09-17 6:52 ` David Marchand 0 siblings, 0 replies; 356+ messages in thread From: David Marchand @ 2026-09-17 6:52 UTC (permalink / raw) To: Prashant Gupta; +Cc: stephen, dev, Jun Yang On Tue, 15 Sept 2026 at 14:03, Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > > From: Jun Yang <jun.yang@nxp.com> > > The configuration parameter in event queue attachment should use > flc and cgid configured in rxq setup. > > Signed-off-by: Jun Yang <jun.yang@nxp.com> > --- > drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 2 +- > drivers/net/dpaa2/dpaa2_ethdev.c | 3 ++- > 2 files changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h > index 12216750a8..f87bf51d09 100644 > --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h > +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h > @@ -1,7 +1,7 @@ > /* SPDX-License-Identifier: BSD-3-Clause > * > * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. > - * Copyright 2016-2024 NXP > + * Copyright 2016-2025 NXP > * > */ > > diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c > index 8cd482b538..77a93ecf91 100644 > --- a/drivers/net/dpaa2/dpaa2_ethdev.c > +++ b/drivers/net/dpaa2/dpaa2_ethdev.c > @@ -2817,11 +2817,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, > struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; > struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; > struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; > - uint8_t flow_id = dpaa2_ethq->flow_id; > + uint8_t flow_id; > struct dpni_queue *cfg; > uint8_t options, priority; > int ret; > > + flow_id = dpaa2_ethq->flow_id; > cfg = dpaa2_ethq->cfg; > > if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) This patch looks like a noop. -- David Marchand ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v3-S3 07/10] drivers: rework dpaa2 Tx confirmation 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (5 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 06/10] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 08/10] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta ` (3 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Mbufs released by Tx confirmation may come from any mempool, so use the RTE mbuf free API instead of returning the buffers directly to the bman pool. The FD FLC field now carries the Tx mbuf pointer so that the confirmation callback can release it to either the platform pool or an external pool. Absolute and dynamic Tx confirmation become independent settings, giving three Tx modes: 1) No confirmation (default). Suited to traffic that is mostly sent from the platform pool. For the few packets from other pools the driver allocates a platform buffer, copies the data and frees the original. 2) Absolute confirmation. Suited to traffic mostly sent from non platform pools. Every Tx packet raises a confirmation, configured at queue setup, and the callback frees the packet. 3) Dynamic confirmation. Confirmation is raised only for packets from non platform pools; the driver marks each packet accordingly at runtime. This suits a roughly even mix of platform and non platform buffers. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- doc/guides/nics/dpaa2.rst | 16 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 2 +- drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 63 +- drivers/net/dpaa2/dpaa2_ethdev.h | 29 +- drivers/net/dpaa2/dpaa2_ptp.c | 4 +- drivers/net/dpaa2/dpaa2_rxtx.c | 1499 ++++++++---------- 8 files changed, 748 insertions(+), 872 deletions(-) diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index faee3a72a2..3a2f2576e8 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -477,10 +477,22 @@ Refer to the document :doc:`build_and_test` for details. of the packet pull command which is issued in the previous cycle. e.g. ``fslmc:dpni.1,drv_no_prefetch=1`` -* Use dev arg option ``drv_tx_conf=1`` to enable TX confirmation mode. - In this mode tx conf queues need to be polled to free the buffers. +* Use dev arg option ``drv_tx_conf=1`` to enable absolute TX confirmation mode. + In this mode every transmitted buffer is returned on a tx conf queue which + needs to be polled to free the buffers. e.g. ``fslmc:dpni.1,drv_tx_conf=1`` +* Use dev arg option ``drv_tx_dyn_conf=1`` to enable dynamic TX confirmation + mode. In this mode only buffers that cannot be released directly by the + hardware (for example indirect, external or shared buffers) are returned on + a tx conf queue which needs to be polled to free the buffers. + e.g. ``fslmc:dpni.1,drv_tx_dyn_conf=1`` + +* Use dev arg option ``drv_tx_dyn_conf_pre=1`` to prefetch the dynamic TX + confirmation queue before transmit. It is used together with + ``drv_tx_dyn_conf=1``. + e.g. ``fslmc:dpni.1,drv_tx_dyn_conf=1,drv_tx_dyn_conf_pre=1`` + * Use dev arg option ``drv_rx_parse_drop=1`` to configure the system to start dropping the error packets in hardware (parse errors). e.g. ``fslmc:dpni.1,drv_rx_parse_drop=1`` diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f87bf51d09..b3aad85d06 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -198,6 +198,7 @@ struct __rte_cache_aligned dpaa2_queue { uint16_t tm_sw_td; /*!< TM software taildrop */ uint64_t offloads; uint64_t lpbk_cntx; + int32_t ts_to_cnfd; uint8_t data_stashing_off; /* NAPI rx-interrupt: per-queue DPCON bound to this FQ at dev_start * (DEST_DPCON, static); the polling worker points the channel's CDAN at diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c index 26ad105c73..fee96b3529 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c @@ -484,7 +484,7 @@ dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, */ /* ... rx buffer layout ... */ - if (priv->flags & DPAA2_TX_DYNAMIC_CONF_ENABLE) { + if (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) { int out_min_hdr_room, in_min_hdr_room; /** Additional headroom layout for IPSec with TX configure * dynamic enabled. diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h index a670098958..b06fa3f644 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019,2022,2024 NXP + * Copyright 2016,2019,2022,2024-2026 NXP * */ @@ -281,6 +281,10 @@ struct dpaa2_faead { /*UPD (Update prepended data)*/ #define DPAA2_ANNOT_FAEAD_UPD 0x00000010 +#define DPAA2_TX_CONFIRM_ENABLE \ + (DPAA2_ANNOT_FAEAD_A4V | DPAA2_ANNOT_FAEAD_EBDD | \ + DPAA2_ANNOT_FAEAD_EBDDV) + /* Debug frame, otherwise supposed to be discarded */ #define DPAA2_ETH_FAS_DISC 0x80000000 /* MACSEC frame */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 77a93ecf91..cfe6179019 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -34,6 +34,8 @@ #define DRIVER_LOOPBACK_MODE "drv_loopback" #define DRIVER_NO_PREFETCH_MODE "drv_no_prefetch" #define DRIVER_TX_CONF "drv_tx_conf" +#define DRIVER_TX_DYNAMIC_CONF "drv_tx_dyn_conf" +#define DRIVER_TX_DYNAMIC_CONF_PREFETCH "drv_tx_dyn_conf_pre" #define DRIVER_RX_PARSE_ERR_DROP "drv_rx_parse_drop" #define DRIVER_ERROR_QUEUE "drv_err_queue" #define DRIVER_NO_TAILDROP "drv_no_taildrop" @@ -522,7 +524,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (priv->flags & DPAA2_TX_CONF_ENABLE) + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else tot_queues = priv->nb_rx_queues + priv->nb_tx_queues; @@ -578,7 +580,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; @@ -693,7 +695,7 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) rte_free(dpaa2_q->cscn); priv->tx_vq[i] = NULL; } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /* cleanup tx conf queue storage */ for (i = 0; i < priv->nb_tx_queues; i++) { dpaa2_q = priv->tx_conf_vq[i]; @@ -1143,6 +1145,13 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, PMD_INIT_FUNC_TRACE(); + /* Tx deferred start is not supported */ + if (tx_conf->tx_deferred_start) { + DPAA2_PMD_ERR("%s:Tx deferred start not supported", + dev->data->name); + return -EINVAL; + } + dpaa2_q->nb_desc = UINT16_MAX; dpaa2_q->offloads = tx_conf->offloads; @@ -1222,7 +1231,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->cb_eqresp_free = dpaa2_dev_free_eqresp_buf; dev->data->tx_queues[tx_queue_id] = dpaa2_q; - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; @@ -3601,10 +3610,22 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) DPAA2_PMD_INFO("DPDK IEEE1588 is enabled"); priv->flags |= DPAA2_TX_CONF_ENABLE; #endif + priv->tx_conf_type = DPAA2_TX_NO_CONF; + /* Used with ``fslmc:dpni.1,drv_tx_conf=1`` */ if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_CONF)) { - priv->flags |= DPAA2_TX_CONF_ENABLE; - DPAA2_PMD_INFO("TX_CONF Enabled"); + priv->tx_conf_type = DPAA2_TX_ABSOLUTE_CONF; + DPAA2_PMD_INFO("TX_ABSOLUTE_CONF Enabled"); + } else if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_DYNAMIC_CONF)) { + priv->tx_conf_type = DPAA2_TX_DYNAMIC_CONF; + DPAA2_PMD_INFO("TX_DYNAMIC_CONF Enabled"); + priv->flags |= DPAA2_TX_PREFETCH_DYNAMIC_CONF; + if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_DYNAMIC_CONF_PREFETCH)) + priv->flags &= ~DPAA2_TX_PREFETCH_DYNAMIC_CONF; + + DPAA2_PMD_INFO("Tx dynamic prefetch confirm %s", + (priv->flags & DPAA2_TX_PREFETCH_DYNAMIC_CONF) ? + "enabled" : "disabled"); } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { @@ -3619,7 +3640,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); @@ -3630,7 +3651,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->num_channels; i++) { /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) { ret = dpni_set_tx_confirmation_mode(dpni_dev, CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); } else { @@ -3667,34 +3688,22 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) /* ... tx buffer layout ... */ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | - DPNI_BUF_LAYOUT_OPT_TIMESTAMP; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; layout.pass_timestamp = true; - } else { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; } + layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, &layout); + DPNI_QUEUE_TX, &layout); if (ret) { DPAA2_PMD_ERR("Error (%d) in setting tx buffer layout", ret); goto init_err; } - - /* ... tx-conf and error buffer layout ... */ - memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; - layout.pass_timestamp = true; - } - layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; - layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX_CONFIRM, &layout); + DPNI_QUEUE_TX_CONFIRM, &layout); if (ret) { - DPAA2_PMD_ERR("Error (%d) in setting tx-conf buffer layout", - ret); + DPAA2_PMD_ERR("Error (%d) in setting tx conf buffer layout", ret); goto init_err; } @@ -3995,6 +4004,8 @@ RTE_PMD_REGISTER_PARAM_STRING(NET_DPAA2_PMD_DRIVER_NAME, DRIVER_LOOPBACK_MODE "=<int> " DRIVER_NO_PREFETCH_MODE "=<int>" DRIVER_TX_CONF "=<int>" + DRIVER_TX_DYNAMIC_CONF "=<int>" + DRIVER_TX_DYNAMIC_CONF_PREFETCH "=<int>" DRIVER_RX_PARSE_ERR_DROP "=<int>" DRIVER_ERROR_QUEUE "=<int>" DRIVER_NO_TAILDROP "=<int>" diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 6eafa9a9e7..4a710b40ad 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -91,18 +91,14 @@ #define DPAA2_TX_DPNI_LOOPBACK_MODE RTE_BIT32(7) -/* Tx confirmation enabled */ -#define DPAA2_TX_CONF_ENABLE RTE_BIT32(8) +#define DPAA2_TX_PREFETCH_DYNAMIC_CONF RTE_BIT32(8) -/* Tx dynamic confirmation enabled, - * only valid with Tx confirmation enabled. - */ -#define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ #define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_SCHED_STRICT_ORDER_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) @@ -452,6 +448,12 @@ struct dpaa2_dev_meter { uint32_t policy_id; }; +enum dpaa2_tx_conf_type { + DPAA2_TX_NO_CONF, + DPAA2_TX_ABSOLUTE_CONF, + DPAA2_TX_DYNAMIC_CONF +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -467,6 +469,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + enum dpaa2_tx_conf_type tx_conf_type; int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; @@ -511,10 +514,10 @@ struct dpaa2_dev_priv { int rx_ts_offset; uint64_t rx_ts_flag; - /* stores pointer to next tx_conf queue that should be processed, + /* stores next tx queue to be confirmed that should be processed, * it corresponds to last packet transmitted */ - struct dpaa2_queue *next_tx_conf_queue; + struct dpaa2_queue *next_txq_to_cnf; struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; @@ -647,7 +650,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); -uint16_t dpaa2_dev_tx_conf(void *queue) __rte_unused; +uint16_t dpaa2_dev_tx_conf(void *txq, int drain); int dpaa2_timesync_enable(struct rte_eth_dev *dev); int dpaa2_timesync_disable(struct rte_eth_dev *dev); @@ -664,6 +667,12 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); + +struct rte_mbuf *__rte_hot +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); +struct rte_mbuf *__rte_hot +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); + int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index 751e558c73..c845291c68 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -111,9 +111,9 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; - if (priv->next_tx_conf_queue) { + if (priv->next_txq_to_cnf) { while (!priv->tx_timestamp) - dpaa2_dev_tx_conf(priv->next_tx_conf_queue); + dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); } else { return -1; } diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index a03e3fd8db..301b389e43 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2026 NXP * */ @@ -75,6 +75,23 @@ dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, DPAA2_RESET_FD_FLC(_fd); \ } while (0) +/* Build a contiguous FD which is returned on the Tx confirmation queue. + * The buffer is not released by the hardware, so an invalid buffer pool + * ID is programmed and the mbuf is carried in the FLC to be freed once + * the confirmation is dequeued. + */ +static inline void +dpaa2_mbuf_to_conf_contig_fd(struct rte_mbuf *mbuf, struct qbman_fd *fd) +{ + DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(mbuf)); + DPAA2_SET_FD_LEN(fd, mbuf->data_len); + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + DPAA2_SET_FD_OFFSET(fd, mbuf->data_off); + DPAA2_SET_FD_FRC(fd, 0); + DPAA2_RESET_FD_CTRL(fd); + DPAA2_SET_FD_FLC(fd, mbuf); +} static inline void dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, @@ -98,7 +115,6 @@ dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, m->hash.rss); } } - static void __rte_hot dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, struct rte_mbuf *m, const struct qbman_fd *fd, @@ -237,13 +253,6 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, "(4)=0x%" PRIx64 "\t", annotation->word3, annotation->word4); -#if defined(RTE_LIBRTE_IEEE1588) - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) { - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST; - } -#endif - if (BIT_ISSET_AT_POS(annotation->word3, L2_VLAN_1_PRESENT)) { vlan_tci = rte_pktmbuf_mtod_offset(mbuf, uint16_t *, (VLAN_TCI_OFFSET_1(annotation->word5) >> 16)); @@ -367,13 +376,13 @@ dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, return dpaa2_dev_rx_parse_slow(mbuf, annotation); } -static inline struct rte_mbuf *__rte_hot +struct rte_mbuf *__rte_hot dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; - size_t sg_addr, fd_addr; + size_t fd_addr; int i = 0; - void *hw_annot_addr; + void *hw_annot_addr, *sg_addr; struct rte_mbuf *first_seg, *next_seg, *cur_seg, *temp; fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); @@ -383,7 +392,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) sgt = (struct qbman_sge *)(fd_addr + DPAA2_GET_FD_OFFSET(fd)); sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); /* First Scatter gather entry */ first_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, @@ -413,8 +422,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) cur_seg = first_seg; while (!DPAA2_SG_IS_FINAL(sge) && i < DPAA2_MAX_SGS) { sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR( - DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); next_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, rte_dpaa2_bpid_info[DPAA2_GET_FLE_BPID(sge)].meta_data_size); next_seg->buf_addr = (uint8_t *)sg_addr; @@ -442,7 +450,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return (void *)first_seg; } -static inline struct rte_mbuf *__rte_hot +struct rte_mbuf *__rte_hot dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); @@ -499,119 +507,295 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return mbuf; } +static void dpaa2_dev_tx_enable_tstamp(struct qbman_fd *fd) +{ + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + + /* Set frame annotation status field as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FASV; + + /* Set frame annotation egress action descriptor as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; + + /* Set Annotation Length as 128B */ + (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD); +} + +static inline struct rte_mbuf * +dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) +{ + struct rte_mbuf *mc = rte_pktmbuf_alloc(mp); + + if (!mc) + return NULL; + if ((mc->data_off + sgm->data_len) > mc->buf_len) { + rte_pktmbuf_free(mc); + return NULL; + } + rte_memcpy(rte_pktmbuf_mtod(mc, void *), + rte_pktmbuf_mtod(sgm, void *), sgm->data_len); + mc->pkt_len = sgm->data_len; + mc->data_len = sgm->data_len; + mc->next = NULL; + + return mc; +} + +static inline void +dpaa2_dev_tx_config_dynamic_confirm(struct qbman_fd *fd, + struct dpaa2_queue *txq, int enable, int tstamp) +{ + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + + if (tstamp) { + DPAA2_SET_FD_FRC(fd, + DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV | DPAA2_FD_FRC_FASV); + fd->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + } else { + DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV); + } + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + if (enable) { + fd_faead->fqid = txq->tx_conf_queue->fqid; + fd_faead->ctrl = DPAA2_TX_CONFIRM_ENABLE; + if (tstamp) { + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | + DPAA2_ANNOT_FAEAD_UPD); + } + } else { + fd_faead->fqid = 0; + fd_faead->ctrl &= (~DPAA2_TX_CONFIRM_ENABLE); + } +} + +static int +dpaa2_dev_tx_no_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf, + struct rte_mempool *hw_mp) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg, *mi, *prev, *copy_mbuf; + + cur_seg = mbuf; + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + mi = rte_mbuf_from_indirect(cur_seg); + if (rte_mbuf_refcnt_read(mi) > 1) + rte_mbuf_refcnt_update(mi, -1); + else + rte_pktmbuf_free_seg(mi); + copy_mbuf->next = cur_seg->next; + if (prev) + prev->next = copy_mbuf; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + if (unlikely(RTE_MBUF_HAS_EXTBUF(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index)) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + + copy_mbuf->next = cur_seg->next; + + if (prev) + prev->next = copy_mbuf; + if (rte_mbuf_refcnt_read(cur_seg) > 1) + rte_mbuf_refcnt_update(cur_seg, -1); + else + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + if (unlikely(rte_mbuf_refcnt_read(cur_seg) > 1)) { + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + rte_mbuf_refcnt_update(cur_seg, -1); + } else { + DPAA2_SET_FLE_BPID(sge, mempool_to_bpid(cur_seg->pool)); + } + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); + + return 0; +} + +static void +dpaa2_dev_tx_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg = mbuf, *mi, *prev; + + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + mi = rte_mbuf_from_indirect(cur_seg); + mi->next = cur_seg->next; + if (prev) + prev->next = mi; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = mi; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); +} + static int __rte_noinline __rte_hot -eth_mbuf_to_sg_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *free_buf, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf, int tstamp) { - struct rte_mbuf *cur_seg = mbuf, *mi, *temp; - struct qbman_sge *sgt, *sge = NULL; - int i, offset = 0; + struct rte_mbuf *cur_seg = mbuf, *sg_mbuf; + struct qbman_sge *sgt; + int offset = 0, ret, need_dyconf = false, need_conf = false; + uint16_t nb_segs = mbuf->nb_segs; + uint32_t sg_size = nb_segs * sizeof(struct qbman_sge); + struct rte_mempool *mp; -#ifdef RTE_LIBRTE_IEEE1588 - /* annotation area for timestamp in first buffer */ - offset = 0x64; -#endif - if (RTE_MBUF_DIRECT(mbuf) && - (mbuf->data_off > (mbuf->nb_segs * sizeof(struct qbman_sge) - + offset))) { - temp = mbuf; - if (rte_mbuf_refcnt_read(temp) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - fd->simple.bpid_offset = 0; + if (conf == DPAA2_TX_DYNAMIC_CONF) { + while (cur_seg) { + if (!RTE_MBUF_DIRECT(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index || + rte_mbuf_refcnt_read(cur_seg) > 1 || tstamp) { + need_dyconf = true; + break; + } + cur_seg = cur_seg->next; + } + cur_seg = mbuf; + } + if (need_dyconf || conf == DPAA2_TX_ABSOLUTE_CONF) + need_conf = true; + + if (need_dyconf || tstamp) + offset = DPAA2_FD_PTA_SIZE + DPAA2_DYN_TX_MIN_FD_OFFSET; + + if (mbuf->pool->ops_index == hw_mp->ops_index && + RTE_MBUF_DIRECT(mbuf) && + mbuf->data_off > RTE_ALIGN(sg_size + offset, 8)) { + sg_mbuf = mbuf; + mp = mbuf->pool; + if (need_conf) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); DPAA2_SET_FD_IVP(fd); - rte_mbuf_refcnt_update(temp, -1); } else { - DPAA2_SET_ONLY_FD_BPID(fd, bpid); + if (unlikely(rte_mbuf_refcnt_read(sg_mbuf) > 1)) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + rte_mbuf_refcnt_update(sg_mbuf, -1); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(mp)); + } + } #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif - } DPAA2_SET_FD_OFFSET(fd, offset); } else { - temp = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); - if (temp == NULL) { + sg_mbuf = NULL; + if (dpaa2_tx_sg_pool) + sg_mbuf = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); + if (!sg_mbuf) { DPAA2_PMD_DP_DEBUG("No memory to allocate S/G table"); return -ENOMEM; } - DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); - DPAA2_SET_FD_OFFSET(fd, temp->data_off); + if (need_conf) { + if (need_dyconf) + sg_mbuf->data_off = RTE_ALIGN(offset, 8); + else + sg_mbuf->data_off = RTE_PKTMBUF_HEADROOM; + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); + } + DPAA2_SET_FD_OFFSET(fd, sg_mbuf->data_off); + offset = sg_mbuf->data_off; #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif } - DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(temp)); + + /*Set Scatter gather table and Scatter gather entries*/ + sgt = (void *)((size_t)sg_mbuf->buf_addr + offset); + DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(sg_mbuf)); DPAA2_SET_FD_LEN(fd, mbuf->pkt_len); DPAA2_FD_SET_FORMAT(fd, qbman_fd_sg); DPAA2_RESET_FD_FRC(fd); DPAA2_RESET_FD_CTRL(fd); - DPAA2_RESET_FD_FLC(fd); - /*Set Scatter gather table and Scatter gather entries*/ - sgt = (struct qbman_sge *)( - (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) - + DPAA2_GET_FD_OFFSET(fd)); + if (need_conf) + DPAA2_SET_FD_FLC(fd, sg_mbuf); + else + DPAA2_RESET_FD_FLC(fd); + if (need_dyconf) + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); + else if (tstamp) + dpaa2_dev_tx_enable_tstamp(fd); - for (i = 0; i < mbuf->nb_segs; i++) { - sge = &sgt[i]; - /*Resetting the buffer pool id and offset field*/ - sge->fin_bpid_offset = 0; - DPAA2_SET_FLE_ADDR(sge, rte_pktmbuf_iova(cur_seg)); - sge->length = cur_seg->data_len; - if (RTE_MBUF_DIRECT(cur_seg)) { - /* if we are using inline SGT in same buffers - * set the FLE FMT as Frame Data Section - */ - if (temp == cur_seg) { - DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); - DPAA2_SET_FLE_IVP(sge); - } else { - if (rte_mbuf_refcnt_read(cur_seg) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - rte_mbuf_refcnt_update(cur_seg, -1); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(cur_seg->pool)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)cur_seg), - (void **)&cur_seg, 1, 0); -#endif - } - } - } else if (RTE_MBUF_HAS_EXTBUF(cur_seg)) { - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FLE_IVP(sge); - } else { - /* Get owner MBUF from indirect buffer */ - mi = rte_mbuf_from_indirect(cur_seg); - if (rte_mbuf_refcnt_read(mi) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * owner buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(mi->pool)); - rte_mbuf_refcnt_update(mi, 1); - } - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - } - cur_seg = cur_seg->next; + if (cur_seg != sg_mbuf && need_conf) + sg_mbuf->next = cur_seg; + + if (need_conf) { + dpaa2_dev_tx_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, sg_mbuf); + } else { + ret = dpaa2_dev_tx_no_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, + sg_mbuf, hw_mp); + if (ret) + return ret; } - DPAA2_SG_SET_FINAL(sge, true); + if (dy_conf && need_dyconf) + *dy_conf = true; + return 0; } @@ -632,101 +816,56 @@ dpaa2_dev_prefetch_next_psr(const struct qbman_result *dq) rte_prefetch0(&annotation->word3); } -static void -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) __rte_unused; - -static void __rte_noinline __rte_hot -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +static int __rte_noinline __rte_hot +dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf, int tstamp) { - DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, bpid); + int need_dyconf = false, need_conf = false; + struct rte_mbuf *mi; + struct rte_mbuf *copy_mbuf; + int ret = 0; - DPAA2_PMD_DP_DEBUG("mbuf =%p, mbuf->buf_addr =%p, off = %d," - "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", - mbuf, mbuf->buf_addr, mbuf->data_off, - DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd)); - if (RTE_MBUF_DIRECT(mbuf)) { + if (unlikely(RTE_MBUF_CLONED(mbuf))) { + mi = rte_mbuf_from_indirect(mbuf); if (rte_mbuf_refcnt_read(mbuf) > 1) { - DPAA2_SET_FD_IVP(fd); rte_mbuf_refcnt_update(mbuf, -1); + } else { + rte_pktmbuf_init(mbuf->pool, NULL, mbuf, 0); + rte_pktmbuf_free(mbuf); } -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - else - rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf), - (void **)&mbuf, 1, 0); -#endif - } else if (RTE_MBUF_HAS_EXTBUF(mbuf)) { - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FD_IVP(fd); + mbuf = mi; + } + if (conf == DPAA2_TX_DYNAMIC_CONF && + (mbuf->pool->ops_index != hw_mp->ops_index || + RTE_MBUF_HAS_EXTBUF(mbuf) || + rte_mbuf_refcnt_read(mbuf) > 1 || tstamp)) + need_dyconf = true; + if (conf == DPAA2_TX_ABSOLUTE_CONF || need_dyconf) + need_conf = true; + + if (need_conf) { + dpaa2_mbuf_to_conf_contig_fd(mbuf, fd); + } else if (mbuf->pool->ops_index == hw_mp->ops_index) { + DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, mempool_to_bpid(mbuf->pool)); } else { - struct rte_mbuf *mi; - - mi = rte_mbuf_from_indirect(mbuf); - if (rte_mbuf_refcnt_read(mi) > 1) - DPAA2_SET_FD_IVP(fd); - else - rte_mbuf_refcnt_update(mi, 1); - - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(mbuf, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + DPAA2_MBUF_TO_CONTIG_FD(copy_mbuf, fd, mempool_to_bpid(hw_mp)); + rte_pktmbuf_free(mbuf); } -} - -static inline int __rte_hot -eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, uint16_t bpid) -{ - struct rte_mbuf *m; - void *mb = NULL; - if (rte_dpaa2_mbuf_alloc_bulk( - rte_dpaa2_bpid_info[bpid].bp_list->mp, &mb, 1)) { - DPAA2_PMD_DP_DEBUG("Unable to allocated DPAA2 buffer"); - return -1; + if (need_dyconf) { + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); + if (dy_conf) + *dy_conf = true; + } else if (tstamp) { + dpaa2_dev_tx_enable_tstamp(fd); } - m = (struct rte_mbuf *)mb; - memcpy((char *)m->buf_addr + mbuf->data_off, - (void *)((char *)mbuf->buf_addr + mbuf->data_off), - mbuf->pkt_len); - - /* Copy required fields */ - m->data_off = mbuf->data_off; - m->ol_flags = mbuf->ol_flags; - m->packet_type = mbuf->packet_type; - m->tx_offload = mbuf->tx_offload; - - DPAA2_MBUF_TO_CONTIG_FD(m, fd, bpid); - -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)m), - (void **)&m, 1, 0); -#endif - DPAA2_PMD_DP_DEBUG( - "mbuf: %p, BMAN buf addr: %p, fdaddr: %" PRIx64 ", bpid: %d," - " meta: %d, off: %d, len: %d", - (void *)mbuf, - mbuf->buf_addr, - DPAA2_GET_FD_ADDR(fd), - DPAA2_GET_FD_BPID(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_OFFSET(fd), - DPAA2_GET_FD_LEN(fd)); -return 0; + return ret; } static void @@ -812,7 +951,6 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) dpaa2_dev_rx_parse_offset(priv, mbuf, fd); dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); - DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd), @@ -1237,12 +1375,6 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1273,150 +1405,204 @@ dpaa2_dev_rx_channel(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) return dpaa2_dev_rx_common(queue, bufs, nb_pkts, true); } -uint16_t dpaa2_dev_tx_conf(void *queue) +static inline int +dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, + struct rte_mbuf *mbuf) { - /* Function receive frames for a given device and VQ */ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct qbman_result *dq_storage; + while (mbuf) { + if (mbuf->pool != mp) + return false; + mbuf = mbuf->next; + } + + return true; +} + +uint16_t dpaa2_dev_tx_conf(void *txq, int drain) +{ + /* Function receive frames for a given device and VQ*/ + struct dpaa2_queue *dpaa2_txq = txq; + struct dpaa2_queue *dpaa2_q = dpaa2_txq->tx_conf_queue; + struct qbman_result *dq_storage, *dq_storage1 = NULL; uint32_t fqid = dpaa2_q->fqid; - int ret, num_tx_conf = 0; - uint8_t pending, status, num_pulled; + int ret, pull_size, total = 0, bulk_free; + uint8_t pending, status, idx, buf_idx; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; - struct qbman_release_desc releasedesc; - uint32_t bpid; - uint64_t buf; -#if defined(RTE_LIBRTE_IEEE1588) - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_annot_hdr *annotation; - void *v_addr; - struct rte_mbuf *mbuf; -#endif + struct queue_storage_info_t *q_storage; + struct qbman_result *rst; - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); + struct rte_mbuf *mbufs[dpaa2_dqrr_size]; + struct rte_mempool *mp = NULL; + #define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + +conf_again: + bulk_free = true; + idx = 0; + q_storage = dpaa2_q->q_storage[rte_lcore_id()]; + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); + DPAA2_PMD_ERR("Failure in affining portal"); return 0; } } - swp = DPAA2_PER_LCORE_PORTAL; - do { - dq_storage = dpaa2_q->q_storage[0]->dq_storage[0]; + swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + pull_size = dpaa2_dqrr_size; + if (unlikely(!q_storage->active_dqs)) { + q_storage->toggle = 0; + dq_storage = q_storage->dq_storage[q_storage->toggle]; + q_storage->last_num_pkts = pull_size; qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, + q_storage->last_num_pkts); qbman_pull_desc_set_fq(&pulldesc, fqid); qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - - qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size); - + DPAA2_VADDR_TO_IOVA(dq_storage), 1); + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } while (1) { if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued." - "QBMAN is busy"); + DPAA2_PMD_DP_DEBUG("QBMAN is busy (1)"); /* Portal was busy, try again */ continue; } break; } + q_storage->active_dqs = dq_storage; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage); + } - rte_prefetch0((void *)((size_t)(dq_storage + 1))); - /* Check if the previous issued command is completed. */ - while (!qbman_check_command_complete(dq_storage)) - ; - - num_pulled = 0; - pending = 1; - do { - /* Loop until the dq_storage is updated with - * new token by QBMAN - */ - while (!qbman_check_new_result(dq_storage)) - ; - rte_prefetch0((void *)((size_t)(dq_storage + 2))); - /* Check whether Last Pull command is Expired and - * setting Condition for Loop termination - */ - if (qbman_result_DQ_is_pull_complete(dq_storage)) { - pending = 0; - /* Check for valid frame. */ - status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & - QBMAN_DQ_STAT_VALIDFRAME) == 0)) - continue; - } - if (dpaa2_svr_family != SVR_LX2160A) - /** Packet type is parsed from FRC for LX2160A.*/ - dpaa2_dev_prefetch_next_psr(dq_storage); + dq_storage = q_storage->active_dqs; + rte_prefetch0((void *)(dq_storage)); + rte_prefetch0((void *)(dq_storage + 1)); - fd = qbman_result_DQ_fd(dq_storage); - bpid = DPAA2_GET_FD_BPID(fd); + /* Prepare next pull descriptor. This will give space for the + * prefetching done on DQRR entries + */ + q_storage->toggle ^= 1; + dq_storage1 = q_storage->dq_storage[q_storage->toggle]; + qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, pull_size); + qbman_pull_desc_set_fq(&pulldesc, fqid); + qbman_pull_desc_set_storage(&pulldesc, dq_storage1, + DPAA2_VADDR_TO_IOVA(dq_storage1), 1); - /* Create a release descriptor required for releasing - * buffers into QBMAN - */ - qbman_release_desc_clear(&releasedesc); - qbman_release_desc_set_bpid(&releasedesc, bpid); + /* Check if the previous issued command is completed. + * Also seems like the SWP is shared between the Ethernet Driver + * and the SEC driver. + */ + while (!qbman_check_command_complete(dq_storage)) + ; + if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id)) + clear_swp_active_dqs(q_storage->active_dpio_id); - buf = DPAA2_GET_FD_ADDR(fd); - /* feed them to bman */ - do { - ret = qbman_swp_release(swp, &releasedesc, - &buf, 1); - } while (ret == -EBUSY); + pending = 1; - dq_storage++; - num_tx_conf++; - num_pulled++; -#if defined(RTE_LIBRTE_IEEE1588) - v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); - mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); - - if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - annotation = (struct dpaa2_annot_hdr *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE); - priv->tx_timestamp = annotation->word2; - } -#endif - } while (pending); + do { + /* Loop until the dq_storage is updated with + * new token by QBMAN + */ + while (!qbman_check_new_result(dq_storage)) + ; + rte_prefetch0((void *)(dq_storage + 2)); + /* Check whether Last Pull command is Expired and + * setting Condition for Loop termination + */ + if (qbman_result_DQ_is_pull_complete(dq_storage)) { + pending = 0; + /* Check for valid frame. */ + status = qbman_result_DQ_flags(dq_storage); + if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) + continue; + } - /* Last VDQ provided all packets and more packets are requested */ - } while (num_pulled == dpaa2_dqrr_size); + fd = qbman_result_DQ_fd(dq_storage); + mbufs[idx] = (void *)DPAA2_GET_FD_FLC(fd); + if (unlikely(!mp)) + mp = mbufs[idx]->pool; + if (unlikely(rte_mbuf_refcnt_read(mbufs[idx]) > 1)) + bulk_free = false; + if (bulk_free && + !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) + bulk_free = false; + idx++; + dq_storage++; + if (idx >= dpaa2_dqrr_size) + break; + } while (pending); - dpaa2_q->rx_pkts += num_tx_conf; + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } + /* issue a volatile dequeue command for next pull */ + while (1) { + if (qbman_swp_pull(swp, &pulldesc)) { + DPAA2_PMD_DP_DEBUG("QBMAN is busy (2)"); + continue; + } + break; + } + q_storage->active_dqs = dq_storage1; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage1); - return num_tx_conf; -} -#ifdef RTE_LIBRTE_IEEE1588 -/* Configure the egress frame annotation for timestamp update */ -static void enable_tx_tstamp(struct qbman_fd *fd) -{ - struct dpaa2_faead *fd_faead; + if (bulk_free) { + rte_pktmbuf_free_bulk(mbufs, idx); + } else { + for (buf_idx = 0; buf_idx < idx; buf_idx++) + rte_pktmbuf_free(mbufs[buf_idx]); + } - /* Set frame annotation status field as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FASV; + dpaa2_q->rx_pkts += idx; + total += idx; + if (drain && pending) + goto conf_again; - /* Set frame annotation egress action descriptor as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; + return total; +} - /* Set Annotation Length as 128B */ - (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; +static inline int +dpaa2_dev_tx_fast_mbuf_to_fd(struct rte_eth_dev_data *dev, + struct rte_mbuf *buf, struct qbman_fd *fd, + enum dpaa2_tx_conf_type conf) +{ + struct rte_mempool *mp = buf->pool; + struct dpaa2_dev_priv *priv = dev->dev_private; + + if (likely(RTE_MBUF_DIRECT(buf) && + mp && mp->ops_index == + priv->bp_list->dpaa2_ops_index && + buf->nb_segs == 1 && + rte_mbuf_refcnt_read(buf) == 1)) { + if (unlikely(buf->next)) { + DPAA2_PMD_WARN("Single mbuf has next segment(%p)", + buf->next); + } + if (unlikely(conf == DPAA2_TX_ABSOLUTE_CONF)) + dpaa2_mbuf_to_conf_contig_fd(buf, fd); + else + DPAA2_MBUF_TO_CONTIG_FD(buf, fd, mempool_to_bpid(mp)); +#ifdef RTE_LIBRTE_MEMPOOL_DEBUG + rte_mempool_check_cookies(rte_mempool_from_obj(buf), + (void **)&buf, 1, 0); +#endif + return 0; + } - /* enable update of confirmation frame annotation */ - fd_faead = (struct dpaa2_faead *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); - fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | - DPAA2_ANNOT_FAEAD_UPD; + return -EAGAIN; } -#endif + /* * Callback to handle sending packets through WRIOP based interface */ @@ -1424,28 +1610,24 @@ uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ - uint32_t loop, retry_count; - int32_t ret; + uint32_t loop, retry_count, i; + int32_t ret, tstamp[MAX_TX_RING_SLOTS]; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; uint32_t frames_to_send; - struct rte_mempool *mp; struct qbman_eq_desc eqdesc; - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; + struct dpaa2_queue *dpaa2_q = queue; struct qbman_swp *swp; uint16_t num_tx = 0; - uint16_t bpid; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct rte_mempool *hw_mp; uint32_t flags[MAX_TX_RING_SLOTS] = {0}; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } @@ -1453,19 +1635,17 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) swp = DPAA2_PER_LCORE_PORTAL; DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); + eth_data, dpaa2_q->fqid); -#ifdef RTE_LIBRTE_IEEE1588 - /* IEEE1588 driver need pointer to tx confirmation queue - * corresponding to last packet transmitted for reading - * the timestamp - */ - if ((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - priv->next_tx_conf_queue = dpaa2_q->tx_conf_queue; - dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue); - priv->tx_timestamp = 0; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + return 0; } -#endif + hw_mp = priv->bp_list->mp; + + if (dpaa2_q->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q, false); /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc); @@ -1473,214 +1653,119 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) qbman_eq_desc_set_fq(&eqdesc, dpaa2_q->fqid); /*Clear the unused FD fields before sending*/ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - - for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn(*bufs)) { - uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; - - flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | - dqrr_index; - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); - *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; - } +tx_again: + /*Check if the queue is congested*/ + retry_count = 0; + while (qbman_result_SCN_state(dpaa2_q->cscn)) { + retry_count++; + /* Retry for some time before giving up */ + if (retry_count > CONG_RETRY_COUNT) + goto skip_tx; + } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], mempool_to_bpid(mp)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies - (rte_mempool_from_obj((void *)*bufs), - (void **)bufs, 1, 0); -#endif - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? + dpaa2_eqcr_size : nb_pkts; - if (unlikely(RTE_MBUF_HAS_EXTBUF(*bufs))) { - if (unlikely((*bufs)->nb_segs > 1)) { - mp = (*bufs)->pool; - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - mempool_to_bpid(mp))) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, 0); - } - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } + for (loop = 0; loop < frames_to_send; loop++) { + dy_conf[loop] = false; + if (*dpaa2_seqn(*bufs)) { + uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; + + flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; + DPAA2_PER_LCORE_DQRR_SIZE--; + DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); + *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; + } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); + if (unlikely((*bufs)->ol_flags + & RTE_MBUF_F_TX_VLAN)) { + ret = rte_vlan_insert(bufs); + if (ret) goto send_n_return; - } + } - if (unlikely((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN)) { - int ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR("S/G support not added" - " for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif + tstamp[loop] = false; + + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { bufs++; + continue; } - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], &flags[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); + } else { + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } + if (ret) + goto send_n_return; + bufs++; + } - num_tx += loop; - nb_pkts -= loop; + loop = 0; + retry_count = 0; + while (loop < frames_to_send) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, + &fd_arr[loop], &flags[loop], + frames_to_send - loop); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { + num_tx += loop; + nb_pkts -= loop; + goto send_n_return; + } + } else { + loop += ret; + retry_count = 0; + } } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); + num_tx += loop; + nb_pkts -= loop; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + for (i = 0; i < loop; i++) { + if (tstamp[i]) + dpaa2_q->tx_conf_queue->ts_to_cnfd++; + } } + if (nb_pkts > 0) + goto tx_again; + + dpaa2_q->tx_pkts += num_tx; return num_tx; send_n_return: /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[i], - &flags[i], - loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } + retry_count = 0; + i = 0; + while (i < loop) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, &fd_arr[i], + &flags[i], loop - i); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + break; + } else { + i += ret; + retry_count = 0; } - num_tx += i; - } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); + num_tx += i; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + loop = i; + for (i = 0; i < loop; i++) { + if (tstamp[i]) + dpaa2_q->tx_conf_queue->ts_to_cnfd++; + } } - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; +skip_tx: dpaa2_q->tx_pkts += num_tx; return num_tx; @@ -1755,149 +1840,110 @@ dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_tx_multi_txq_ordered) uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, - struct rte_mbuf **bufs, uint16_t nb_pkts) + struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to multiple queues respectively.*/ - uint32_t loop, i, retry_count; - int32_t ret; + uint32_t loop, retry_count, sent = 0, i; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS]; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; - struct rte_mempool *mp; + struct rte_mempool *hw_mp; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; struct dpaa2_queue *dpaa2_q[MAX_TX_RING_SLOTS]; struct qbman_swp *swp; - uint16_t bpid; - struct rte_mbuf *mi; struct rte_eth_dev_data *eth_data; struct dpaa2_dev_priv *priv; struct dpaa2_queue *order_sendq; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } } swp = DPAA2_PER_LCORE_PORTAL; +tx_again: frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - dpaa2_q[loop] = (struct dpaa2_queue *)queue[loop]; + dpaa2_q[loop] = queue[loop]; + if (dpaa2_q[loop]->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q[loop], false); eth_data = dpaa2_q[loop]->eth_data; priv = eth_data->dev_private; - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { + dy_conf[loop] = false; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + ret = -ENOMEM; + goto send_frames; + } + hw_mp = priv->bp_list->mp; + if (!priv->en_loose_ordered && + (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP)) { + if (!num_free_eq_desc) { + num_free_eq_desc = dpaa2_free_eq_descriptors(); if (!num_free_eq_desc) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (!num_free_eq_desc) - goto send_frames; + ret = -EIO; + goto send_frames; } - num_free_eq_desc--; } + num_free_eq_desc--; } DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q[loop]->fqid); + eth_data, dpaa2_q[loop]->fqid); /* Check if the queue is congested */ retry_count = 0; while (qbman_result_SCN_state(dpaa2_q[loop]->cscn)) { retry_count++; /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) + if (retry_count > CONG_RETRY_COUNT) { + ret = -ETIME; goto send_frames; + } } /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); if (*dpaa2_seqn(*bufs) && priv->en_ordered) { - order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); + order_sendq = priv->tx_vq[0]; + dpaa2_set_enqueue_descriptor(order_sendq, *bufs, + &eqdesc[loop]); } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q[loop]->fqid); + qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); + qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_frames; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_frames; - } + tstamp[loop] = false; - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; + bufs++; + continue; + } - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_frames; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_frames; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_frames; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } - + if (ret) + goto send_frames; + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; bufs++; } @@ -1918,237 +1964,30 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, break; } } - - for (i = 0; i < free_count; i++) { - if (buf_to_free[i].pkt_id < loop) - rte_pktmbuf_free_seg(buf_to_free[i].seg); + nb_pkts -= loop; + sent += loop; + for (i = 0; i < loop; i++) { + if (tstamp[i] && dpaa2_q[i]->tx_conf_queue) + dpaa2_q[i]->tx_conf_queue->ts_to_cnfd++; } - return loop; + if (nb_pkts > 0 && !ret) + goto tx_again; + + return sent; } /* Callback to handle sending ordered packets through WRIOP based interface */ uint16_t -dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) +dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) { - /* Function to transmit the frames to given device and VQ*/ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_queue *order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; - struct rte_mempool *mp; - struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; - struct qbman_swp *swp; - uint32_t frames_to_send, num_free_eq_desc; - uint32_t loop, retry_count; - int32_t ret; - uint16_t num_tx = 0; - uint16_t bpid; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint16_t i; + void *mq[nb_pkts]; - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); - if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); - return 0; - } - } - swp = DPAA2_PER_LCORE_PORTAL; + for (i = 0; i < nb_pkts; i++) + mq[i] = queue; - DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); - - /* This would also handle normal and atomic queues as any type - * of packet can be enqueued when ordered queues are being used. - */ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (num_free_eq_desc < frames_to_send) - frames_to_send = num_free_eq_desc; - } - } - - for (loop = 0; loop < frames_to_send; loop++) { - /*Prepare enqueue descriptor*/ - qbman_eq_desc_clear(&eqdesc[loop]); - - if (*dpaa2_seqn(*bufs)) { - /* Use only queue 0 for Tx in case of atomic/ - * ordered packets as packets can get unordered - * when being transmitted out from the interface - */ - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); - } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q->fqid); - } - - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_n_return; - } - - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } - bufs++; - } - - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[loop], &fd_arr[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } - } - - num_tx += loop; - nb_pkts -= loop; - } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; - -send_n_return: - /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[i], &fd_arr[i], loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } - } - num_tx += i; - } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; - dpaa2_q->tx_pkts += num_tx; - - return num_tx; + return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); } /* This function loopbacks all the received packets.*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 08/10] drivers: consume dpaa2 DQRR entries in batches 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (6 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 07/10] drivers: rework dpaa2 Tx confirmation Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 09/10] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta ` (2 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Each DQRR entry consumed by the software portal costs a write to the cache-invalidate DCAP register. The DCAP register also supports a vector mode where a bitmap of DQRR indices is consumed with a single write, so accumulate the indices and flush the vector once half the ring is pending. A smaller threshold gives little benefit, and a threshold close to the ring size starves WRIOP of DQRR space. Because entries are now released in batches, a caller that stops polling a portal must flush the pending vector explicitly. Pass a NULL dequeue result to qbman_swp_dqrr_consume() to do that when the eventdev dequeue finds the portal dry, when the net PMD finishes draining a portal, and when a portal is released back to the bus. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 4 ++ .../fslmc/qbman/include/fsl_qbman_portal.h | 5 +- drivers/bus/fslmc/qbman/qbman_portal.c | 63 +++++++++++++++++-- drivers/bus/fslmc/qbman/qbman_portal.h | 11 +++- drivers/event/dpaa2/dpaa2_eventdev.c | 4 ++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 + 6 files changed, 81 insertions(+), 8 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 20d1bb2a66..cfd9548fb0 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -305,6 +305,10 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) { if (dpio_dev) { + /* consume indices may still be pending in the portal's DQRR + * consume vector; flush them before the portal is released. + */ + qbman_swp_dqrr_consume(dpio_dev->sw_portal, NULL); /* rx-queue interrupts (net PMD) can arm a portal without the * event driver; tear it down unconditionally. Safe when never * armed: intr_deinit returns early if intr is not enabled. diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index b9e7789766..73e57bcdc1 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -451,7 +451,10 @@ void qbman_swp_prefetch_dqrr_next(struct qbman_swp *s); * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from * qbman_swp_dqrr_next(). * @s: the software portal object. - * @dq: the DQRR entry to be consumed. + * @dq: the DQRR entry to be consumed, NULL to consume the entries accumulated + * so far. Entries are accumulated and consumed in batches, so a caller which + * stops polling the portal must call this with a NULL dq to release the + * entries it has already processed. */ __rte_internal void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq); diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index c93bec5dd3..4902ca4ccb 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020,2023-2024 NXP + * Copyright 2018-2020,2023-2024,2026 NXP * */ @@ -9,13 +9,20 @@ #include "qbman_portal.h" #include <eal_export.h> +#include <rte_bitops.h> /* QBMan portal management command codes */ #define QBMAN_MC_ACQUIRE 0x30 #define QBMAN_WQCHAN_CONFIGURE 0x46 /* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ -#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6) +#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) + +/* DCAP consume-index-vector mode: the vector of DQRR indices to consume starts + * at bit 16 of DCAP and bit 8 selects vector mode over single-index mode. + */ +#define DQRR_DCAP_CI_VEC_OFFSET 16 +#define DQRR_DCAP_CI_VEC_SELECT 0x100 /* QBMan FQ management command codes */ #define QBMAN_FQ_SCHEDULE 0x48 @@ -284,6 +291,13 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) p->dqrr.dqrr_size = 8; p->dqrr.reset_bug = 0; } + /* Consume DQRR entries in vector mode by default and flush the vector + * once half the ring is pending. A smaller threshold gives little + * benefit; a threshold close to the ring size starves WRIOP of DQRR + * space and slows its enqueues down. + */ + p->dqrr.ci_vec_en = p->dqrr.dqrr_size <= (32 - DQRR_DCAP_CI_VEC_OFFSET); + p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { @@ -2225,13 +2239,47 @@ const struct qbman_result *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s) return p; } -/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ +/* Write the pending consume vector to DCAP if it holds at least "threshold" + * indices, consuming all of them with a single register access. + */ +static inline void +qbman_swp_dqrr_vec_flush(struct qbman_swp *s, uint8_t threshold) +{ + if (s->dqrr.ci_count < threshold) + return; + + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + s->dqrr.ci_vector | DQRR_DCAP_CI_VEC_SELECT); + s->dqrr.ci_vector = 0; + s->dqrr.ci_count = 0; +} + +/* Add a DQRR index to the pending consume vector, flushing it once the + * configured threshold is reached. + */ +static inline void +qbman_swp_dqrr_vec_consume(struct qbman_swp *s, uint8_t idx) +{ + s->dqrr.ci_vector |= RTE_BIT32(idx + DQRR_DCAP_CI_VEC_OFFSET); + s->dqrr.ci_count++; + qbman_swp_dqrr_vec_flush(s, s->dqrr.ci_flush_th); +} + +/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). + * A NULL dq flushes any indices still pending in the consume vector, which + * the caller must do before it stops polling the portal. + */ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_consume) void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq) { - qbman_cinh_write(&s->sys, - QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); + if (unlikely(dq == NULL)) + qbman_swp_dqrr_vec_flush(s, 1); + else if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, QBMAN_IDX_FROM_DQRR(dq)); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + QBMAN_IDX_FROM_DQRR(dq)); } /* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ @@ -2239,7 +2287,10 @@ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_idx_consume) void qbman_swp_dqrr_idx_consume(struct qbman_swp *s, uint8_t dqrr_index) { - qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); + if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, dqrr_index); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); } /*********************************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.h b/drivers/bus/fslmc/qbman/qbman_portal.h index 1cf7918309..db74db5fe1 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.h +++ b/drivers/bus/fslmc/qbman/qbman_portal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020 NXP + * Copyright 2018-2020, 2026 NXP * */ @@ -93,6 +93,15 @@ struct qbman_swp { uint32_t valid_bit; uint8_t dqrr_size; int reset_bug; + /* Consume index vector: instead of writing DCAP once per + * consumed entry, the indices are accumulated in ci_vector + * and written with a single DCAP access once ci_count + * reaches ci_flush_th. + */ + bool ci_vec_en; + uint8_t ci_count; + uint8_t ci_flush_th; + uint32_t ci_vector; } dqrr; struct { uint32_t pi; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 95d9154b11..5d32bd9fd6 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -320,6 +320,10 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], do { dq = qbman_swp_dqrr_next(swp); if (!dq) { + /* portal is dry: consume whatever is still pending in + * the DQRR consume vector before leaving it idle. + */ + qbman_swp_dqrr_consume(swp, NULL); if (!num_pkts && timeout_ticks) { dpaa2_eventdev_dequeue_wait(timeout_ticks); timeout_ticks = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index cfe6179019..f7cdbbf7d7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3041,6 +3041,8 @@ dpaa2_napi_drain_portal(struct dpaa2_dpio_dev *dpio) while ((dq = qbman_swp_dqrr_next(dpio->sw_portal))) qbman_swp_dqrr_consume(dpio->sw_portal, dq); + /* flush the indices still pending in the DQRR consume vector */ + qbman_swp_dqrr_consume(dpio->sw_portal, NULL); qbman_swp_interrupt_clear_status(dpio->sw_portal, 0xffffffff); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 09/10] drivers: resolve dpaa2 endpoint in the net driver 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (7 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 08/10] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 10/10] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPRC object driver walked every device on the bus and, for each DPNI, issued dprc_get_connection() to find the object it is wired to. Two things are wrong with that. The bus keeps the result in struct rte_dpaa2_device even though only the net driver consumes it, and a failure to resolve one DPNI's endpoint aborted the creation of the whole container. The endpoint name was also formatted from endpoint2 outside the DPNI branch, so non-DPNI devices got a name built from uninitialised or stale data. Move the lookup to dpaa2_dev_init(), which already knows it is dealing with a DPNI and can fail the probe of that one port. This also fills in priv->ep_dev_type, priv->ep_object_id and priv->ep_name, which the net driver reads for MAC-level operations, recycle/loopback configuration and rte_pmd_dpaa2_ep_name(), but which nothing assigned. dpsw endpoints are now recognised, and dpdmux/dpsw names carry the interface index because those endpoints are per-interface. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 3 -- drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 45 +++--------------- drivers/net/dpaa2/dpaa2_ethdev.c | 59 +++++++++++++++++++++++- drivers/net/dpaa2/dpaa2_recycle.c | 15 +++--- 4 files changed, 71 insertions(+), 51 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index b4a5a86318..0d431fdd19 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -104,10 +104,7 @@ struct rte_dpaa2_device { struct rte_device device; /**< Inherit core device */ enum rte_dpaa2_dev_type dev_type; /**< Device Type */ uint16_t object_id; /**< DPAA2 Object ID */ - enum rte_dpaa2_dev_type ep_dev_type; /**< Endpoint Device Type */ struct dpaa2_dprc_dev *container; - uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */ - char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ struct rte_dma_dev *dmadev; /**< DMA device */ diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c index 868ed646af..6441297ecf 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c @@ -27,7 +27,6 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, struct rte_dpaa2_device *obj) { struct dpaa2_dprc_dev *dprc_node; - struct dprc_endpoint endpoint1, endpoint2; struct rte_dpaa2_device *dev; int ret, dprc_id = obj->object_id; @@ -49,45 +48,13 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, return ret; } - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - /** DPRC is always created before it's children are created.*/ + /* DPRC is always created before its children are created, so every + * device scanned so far belongs to this container. Endpoint lookup is + * left to the object drivers, which know how many interfaces their + * object has and can report a failure to their own caller. + */ + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) dev->container = dprc_node; - if (dev->dev_type == DPAA2_ETH) { - int link_state; - - memset(&endpoint1, 0, sizeof(struct dprc_endpoint)); - memset(&endpoint2, 0, sizeof(struct dprc_endpoint)); - strcpy(endpoint1.type, "dpni"); - endpoint1.id = dev->object_id; - ret = dprc_get_connection(&dprc_node->dprc, - CMD_PRI_LOW, - dprc_node->token, - &endpoint1, &endpoint2, - &link_state); - if (ret) { - DPAA2_BUS_ERR("dpni.%d connection failed!", - dev->object_id); - dprc_close(&dprc_node->dprc, CMD_PRI_LOW, - dprc_node->token); - rte_free(dprc_node); - return ret; - } - - if (!strcmp(endpoint2.type, "dpmac")) - dev->ep_dev_type = DPAA2_MAC; - else if (!strcmp(endpoint2.type, "dpni")) - dev->ep_dev_type = DPAA2_ETH; - else if (!strcmp(endpoint2.type, "dpdmux")) - dev->ep_dev_type = DPAA2_MUX; - else - dev->ep_dev_type = DPAA2_UNKNOWN; - - dev->ep_object_id = endpoint2.id; - } else { - dev->ep_dev_type = DPAA2_UNKNOWN; - } - sprintf(dev->ep_name, "%s.%d", endpoint2.type, endpoint2.id); - } TAILQ_INSERT_TAIL(&dprc_dev_list, dprc_node, next); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f7cdbbf7d7..1552d2a25f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -26,6 +26,7 @@ #include <dpaa2_hw_pvt.h> #include <dpaa2_hw_mempool.h> #include <dpaa2_hw_dpio.h> +#include <fsl_dprc.h> #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" @@ -3436,6 +3437,55 @@ dpaa2_get_devargs(struct rte_devargs *devargs, const char *key) return 1; } +/* Resolve the object this DPNI is wired to inside its DPRC container. The + * endpoint decides whether MAC-level operations (link, promisc, flow control) + * are available, and it is reported to the application by + * rte_pmd_dpaa2_ep_name(). + */ +static int +dpaa2_dev_ep_init(struct rte_dpaa2_device *dpaa2_dev, + struct dpaa2_dev_priv *priv) +{ + struct dpaa2_dprc_dev *dprc_node = dpaa2_dev->container; + struct dprc_endpoint endpoint1, endpoint2; + int link_state, ret; + + memset(&endpoint1, 0, sizeof(endpoint1)); + memset(&endpoint2, 0, sizeof(endpoint2)); + strlcpy(endpoint1.type, "dpni", sizeof(endpoint1.type)); + endpoint1.id = dpaa2_dev->object_id; + ret = dprc_get_connection(&dprc_node->dprc, CMD_PRI_LOW, + dprc_node->token, &endpoint1, &endpoint2, + &link_state); + if (ret != 0) + return ret; + + if (strcmp(endpoint2.type, "dpmac") == 0) + priv->ep_dev_type = DPAA2_MAC; + else if (strcmp(endpoint2.type, "dpni") == 0) + priv->ep_dev_type = DPAA2_ETH; + else if (strcmp(endpoint2.type, "dpdmux") == 0) + priv->ep_dev_type = DPAA2_MUX; + else if (strcmp(endpoint2.type, "dpsw") == 0) + priv->ep_dev_type = DPAA2_SW; + else + priv->ep_dev_type = DPAA2_UNKNOWN; + + priv->ep_object_id = endpoint2.id; + + /* dpdmux and dpsw endpoints are per-interface, so the interface index + * is part of the name. + */ + if (priv->ep_dev_type == DPAA2_MUX || priv->ep_dev_type == DPAA2_SW) + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d.%d", + endpoint2.type, endpoint2.id, endpoint2.if_id); + else + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d", + endpoint2.type, endpoint2.id); + + return 0; +} + static int dpaa2_dev_init(struct rte_eth_dev *eth_dev) { @@ -3527,6 +3577,13 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + ret = dpaa2_dev_ep_init(dpaa2_dev, priv); + if (ret) { + DPAA2_PMD_ERR("Failure in get dpni@%d endpoint, err code %d", + hw_id, ret); + goto init_err; + } + ret = dpni_get_api_version(dpni_dev, CMD_PRI_LOW, &priv->dpni_ver_major, &priv->dpni_ver_minor); if (ret) { @@ -3758,7 +3815,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; DPAA2_PMD_INFO("%s: netdev created, connected to %s", - eth_dev->data->name, dpaa2_dev->ep_name); + eth_dev->data->name, priv->ep_name); priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 7569ea9c0d..94ec47a0ad 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -630,18 +630,18 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_MAC) { + if (priv->ep_dev_type == DPAA2_MAC) { /** For dpmac-dpni connection, * try setting serdes loopback as recycle device at first. */ if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; @@ -670,8 +670,8 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_ETH && - dpaa2_dev->object_id == dpaa2_dev->ep_object_id) { + if (priv->ep_dev_type == DPAA2_ETH && + dpaa2_dev->object_id == priv->ep_object_id) { priv->flags |= DPAA2_TX_DPNI_LOOPBACK_MODE; return 0; @@ -684,7 +684,6 @@ int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) { struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct rte_dpaa2_device *dpaa2_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *dpaa2_dev); struct fsl_mc_io *dpni_dev = eth_dev->process_private; struct dpni_port_cfg port_cfg; int ret = 0; @@ -694,7 +693,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) if (priv->flags & DPAA2_TX_SERDES_LOOPBACK_MODE) { if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); @@ -702,7 +701,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v3-S3 10/10] drivers: align dpaa2 event port depths with hardware rings 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (8 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 09/10] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta @ 2026-09-15 12:02 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-15 12:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The event port dequeue and enqueue depths were fixed at 8. A dequeue drains the portal DQRR and an enqueue fills the EQCR, so the real limits are the sizes of those two rings, which differ per SoC and are known at run time. Report them instead, adding qbman_swp_portal_dqrr_size() to query the DQRR size (the EQCR size is already available as dpaa2_eqcr_size). The Tx adapter enqueue helpers sized their on-stack mbuf arrays from the advertised enqueue depth, which no longer bounds the burst the adapter may hand them, so bound the copy by the array itself and transmit in chunks. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- .../fslmc/qbman/include/fsl_qbman_portal.h | 7 ++ drivers/bus/fslmc/qbman/qbman_portal.c | 15 ++++ drivers/event/dpaa2/dpaa2_eventdev.c | 72 ++++++++++++------- drivers/event/dpaa2/dpaa2_eventdev.h | 4 +- 4 files changed, 69 insertions(+), 29 deletions(-) diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index 73e57bcdc1..fb1c6046ae 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -1222,6 +1222,13 @@ __rte_internal int qbman_swp_acquire(struct qbman_swp *s, uint16_t bpid, uint64_t *buffers, unsigned int num_buffers); +/** + * qbman_swp_portal_dqrr_size() - Number of entries in a portal's DQRR. + * @p: the software portal object, NULL to query the SoC's DQRR size. + */ +__rte_internal +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p); + /*****************/ /* FQ management */ /*****************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index 4902ca4ccb..462e2ed75f 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -73,6 +73,11 @@ enum qbman_sdqcr_fc { static struct qbman_swp *portal_idx_map[MAX_QBMAN_PORTALS]; uint32_t qman_version; +/* DQRR size of the portals initialised so far. All portals of a SoC have the + * same size, so this doubles as the SoC's DQRR size for callers that have no + * portal at hand. + */ +static uint32_t dpaa2_portal_dqrr_size = 8; /* Internal Function declaration */ static int @@ -239,6 +244,15 @@ static int (*qbman_swp_release_ptr)(struct qbman_swp *s, const uint64_t *buffers, unsigned int num_buffers) = qbman_swp_release_direct; +RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_portal_dqrr_size) +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p) +{ + if (p != NULL) + return p->dqrr.dqrr_size; + + return dpaa2_portal_dqrr_size; +} + /*********************************/ /* Portal constructor/destructor */ /*********************************/ @@ -298,6 +312,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) */ p->dqrr.ci_vec_en = p->dqrr.dqrr_size <= (32 - DQRR_DCAP_CI_VEC_OFFSET); p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; + dpaa2_portal_dqrr_size = p->dqrr.dqrr_size; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 5d32bd9fd6..ddcf7b3678 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017,2019-2022 NXP + * Copyright 2017,2019-2022,2026 NXP */ #include <assert.h> @@ -389,10 +389,11 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, /* we only support dpio up to number of cores */ if (dev_info->max_event_ports > rte_lcore_count()) dev_info->max_event_ports = rte_lcore_count(); - dev_info->max_event_port_dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - dev_info->max_event_port_enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + /* A dequeue drains the portal DQRR and an enqueue fills the EQCR, so + * the hardware ring sizes are the real limits. + */ + dev_info->max_event_port_dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + dev_info->max_event_port_enqueue_depth = dpaa2_eqcr_size; dev_info->max_num_events = DPAA2_EVENT_MAX_NUM_EVENTS; dev_info->event_dev_cap = RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED | RTE_EVENT_DEV_CAP_ATOMIC | @@ -527,12 +528,9 @@ dpaa2_eventdev_port_def_conf(struct rte_eventdev *dev, uint8_t port_id, RTE_SET_USED(dev); RTE_SET_USED(port_id); - port_conf->new_event_threshold = - DPAA2_EVENT_MAX_NUM_EVENTS; - port_conf->dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - port_conf->enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + port_conf->new_event_threshold = DPAA2_EVENT_MAX_NUM_EVENTS; + port_conf->dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + port_conf->enqueue_depth = dpaa2_eqcr_size; port_conf->event_port_cfg = 0; } @@ -977,18 +975,31 @@ dpaa2_eventdev_txa_enqueue_same_dest(void *port, struct rte_event ev[], uint16_t nb_events) { - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH], *m0; - uint8_t qid, i; + struct rte_mbuf *m[MAX_TX_RING_SLOTS], *m0; + uint16_t sent = 0, burst, i, port_id; + uint8_t qid; RTE_SET_USED(port); - m0 = (struct rte_mbuf *)ev[0].mbuf; + m0 = ev[0].mbuf; qid = rte_event_eth_tx_adapter_txq_get(m0); + port_id = m0->port; + + /* The advertised enqueue depth is the EQCR size, which may exceed the + * on-stack burst array, so transmit in ring-sized chunks. + */ + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) + m[i] = ev[sent + i].mbuf; + + i = rte_eth_tx_burst(port_id, qid, m, burst); + sent += i; + if (i < burst) + break; + } - for (i = 0; i < nb_events; i++) - m[i] = (struct rte_mbuf *)ev[i].mbuf; - - return rte_eth_tx_burst(m0->port, qid, m, nb_events); + return sent; } static uint16_t @@ -996,19 +1007,28 @@ dpaa2_eventdev_txa_enqueue(void *port, struct rte_event ev[], uint16_t nb_events) { - void *txq[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - uint8_t qid, i; + void *txq[MAX_TX_RING_SLOTS]; + struct rte_mbuf *m[MAX_TX_RING_SLOTS]; + uint16_t sent = 0, burst, i; + uint8_t qid; RTE_SET_USED(port); - for (i = 0; i < nb_events; i++) { - m[i] = (struct rte_mbuf *)ev[i].mbuf; - qid = rte_event_eth_tx_adapter_txq_get(m[i]); - txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) { + m[i] = ev[sent + i].mbuf; + qid = rte_event_eth_tx_adapter_txq_get(m[i]); + txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + } + + i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); + sent += i; + if (i < burst) + break; } - return dpaa2_dev_tx_multi_txq_ordered(txq, m, nb_events); + return sent; } static struct eventdev_ops dpaa2_eventdev_ops = { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index 3883a26c91..a054dfdbd7 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017 NXP + * Copyright 2017,2026 NXP */ #ifndef __DPAA2_EVENTDEV_H__ @@ -22,8 +22,6 @@ #define DPAA2_EVENT_MAX_QUEUE_FLOWS 2048 #define DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS 8 #define DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS 0 -#define DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH 8 -#define DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH 8 #define DPAA2_EVENT_MAX_NUM_EVENTS (INT32_MAX - 1) #define DPAA2_EVENT_QUEUE_ATOMIC_FLOWS 2048 -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta ` (9 preceding siblings ...) 2026-09-15 12:02 ` [PATCH v3-S3 10/10] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 01/65] net/dpaa2: refactor and optimize Rx parser result decode Prashant Gupta ` (64 more replies) 10 siblings, 65 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev This is the final DPAA2 upstreaming sub-series, applied on top of v7-S1 ("dpaa2: bus, DMA and mempool base fixes") and v14-S2 ("net/dpaa2 updates"). The series reworks the DPAA2 datapath, flow steering, metering, eventdev integration and fslmc infrastructure. It consolidates device configuration handling, improves queue and portal management, and adds support for additional DPNI, eventdev and datapath capabilities. Highlights: - add DMA bypass translation support and table-driven devargs parsing; - optimize Tx queue, channel and dequeue processing paths; - centralize MC version, SoC detection and endpoint handling; - rework RSS, flow steering, QoS and default action programming; - add rte_mtr support and meter rte_flow actions; - improve eventdev scheduling, DPCI support and multi-port operation; - support runtime IEEE1588 timestamping; - rework xstats collection and MAC statistics handling; - unify enqueue/dequeue datapaths across net, crypto and eventdev; - add Tx fast paths and reduce confirmation overhead. Every commit builds cleanly with arm64 and -Werror and the series remains bisectable. Breeson Francis (1): net/dpaa2: rework xstats with page table and MAC support Hemant Agrawal (1): net/dpaa2: reject Rx queue deferred start Jun Yang (63): net/dpaa2: refactor and optimize Rx parser result decode net/dpaa2: generate devargs table and string from one list crypto/dpaa2_sec: use table-driven devargs parsing dma/dpaa2: use table-driven devargs parsing net/dpaa2: unify debug dump via log based helpers net/dpaa2: expose Rx L3/L4/L5 offsets via mbuf dynfield net/dpaa2: optimize dpaa2 Tx queue and channel mapping bus/fslmc: split bus-level device walk from VFIO primitives bus/fslmc: centralize MC version and SoC detection in the bus layer net/dpaa2: remove unused soft parser loader net/dpaa2: cache per-rxq DPNI queue cfg and share CGID per TC The dpaa2 PMD so far supported only two Tx buffer release schemes: direct release by hardware, and an absolute Tx confirmation mode (drv_tx_conf=1) where every transmitted buffer is returned on a Tx confirmation queue that software must poll to free the buffers. Absolute confirmation adds a confirmation descriptor and a poll cost for all packets, even those the hardware could free on its own. net/dpaa2: support runtime IEEE1588 timestamping bus/fslmc: consume dpaa2 DQRR entries in batches bus/fslmc: align dpaa2 event port depths with hardware rings net/dpaa2: support multi-DPNI FS redirect and QoS table v3 net/dpaa2: unify xstats layout and add DPMAC counter struct net/dpaa2: reimplement xstats_get() on top of xstats_get_by_id() net/dpaa2: fetch only requested MAC xstats in one MC call net/dpaa2: rework flow with per-table profile and group types net/dpaa2: reimplement RSS distribution via rte_flow net/dpaa2: expand IP address extracts for RSS hashing net/dpaa2: add policer v2 MC command and L2/L3 byte units net/dpaa2: support rte_mtr and METER rte_flow action net/dpaa2: program flow table miss actions via rte_flow net/dpaa2: support DCB Rx mode via rte_flow bus/fslmc: support DPCI peer and dynamic queues bus/fslmc: add alloc/free DPIO API for non-affine portals event/dpaa2: rework event port model and DPCI handling event/dpaa2: fix Tx adapter enqueue for mixed destinations event/dpaa2: rework self test for dynamic link and balance check event/dpaa2: add DPCON based standalone Rx scheduler event/dpaa2: add push mode to DPCON Rx scheduler event/dpaa2: drain Rx scheduler queues on destroy event/dpaa2: track and detach attached Rx queues net/dpaa2: add multi-port Tx API event/dpaa2: limit attached Rx flows per event queue eventdev: fix port link/unlink callback return documentation event/dpaa2: allow event queue link to multiple ports event/dpaa2: report available DPIO count and fix create cleanup event/dpaa2: use event port DPIO for dequeue wait bus/fslmc: consolidate DPIO interrupt setup and bound coalescing event/dpaa2: honor configured dequeue timeout bus/fslmc: use EAL API for DPIO interrupt bus/fslmc: defer DPIO interrupt setup and bind portal to worker core bus/fslmc: move Tx SG mempool to fslmc bus net/dpaa2: move DPNI endpoint lookup out of the fslmc bus net/dpaa2: add APIs to query device info and set default action net/dpaa2: consolidate dequeue paths and optimize fast path net/dpaa2: bind per-queue DPIO for rx-queue interrupts net/dpaa2: add API to clean Tx confirmation queue event/dpaa2: fix DQRR held buffer accounting on enqueue bus/fslmc: store dequeue dpio in mbuf seq dynfield bus/fslmc: use explicit flags for mbuf seqn encoding net/dpaa2: unify tx burst path for ordered and atomic enqueue crypto/dpaa2_sec: unify enqueue burst path for ordered enqueue bus/fslmc: track atomic DCA context per dequeue dpio bus/fslmc: move enqueue response descriptors to per-queue event/dpaa2: add ordered schedule type support bus/fslmc: make DPAA2 ORP/ODP ordering per-queue instead of per-device event/dpaa2: support multi-port enqueue in selftest random event generator event/dpaa2: do not fail device creation on DPCI errors net/dpaa2: add Tx fast path for no-confirmation case doc/guides/nics/dpaa2.rst | 29 +- doc/guides/rel_notes/release_26_11.rst | 10 + drivers/bus/fslmc/bus_fslmc_driver.h | 46 +- drivers/bus/fslmc/fslmc_bus.c | 321 +- drivers/bus/fslmc/fslmc_logs.h | 2 + drivers/bus/fslmc/fslmc_vfio.c | 562 +- drivers/bus/fslmc/fslmc_vfio.h | 72 +- drivers/bus/fslmc/mc/dpci.c | 37 +- drivers/bus/fslmc/mc/fsl_dpci.h | 12 +- drivers/bus/fslmc/portal/dpaa2_hw_dpci.c | 304 +- drivers/bus/fslmc/portal/dpaa2_hw_dpcon.c | 25 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 668 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 37 +- drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 52 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 305 +- drivers/bus/fslmc/private.h | 15 +- .../fslmc/qbman/include/fsl_qbman_portal.h | 24 +- drivers/bus/fslmc/qbman/qbman_portal.c | 100 +- drivers/bus/fslmc/qbman/qbman_portal.h | 11 +- drivers/bus/fslmc/qbman/qbman_sys.h | 4 +- drivers/common/dpaax/dpaax_devarg.h | 69 + drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 559 +- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 11 +- drivers/dma/dpaa2/dpaa2_qdma.c | 92 +- drivers/dma/dpaa2/dpaa2_qdma.h | 15 +- drivers/event/dpaa2/dpaa2_eventdev.c | 1266 ++- drivers/event/dpaa2/dpaa2_eventdev.h | 61 +- drivers/event/dpaa2/dpaa2_eventdev_selftest.c | 370 +- drivers/event/dpaa2/dpaa2_scheduler.c | 673 ++ drivers/event/dpaa2/meson.build | 3 +- drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 544 -- drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 3201 ++++--- drivers/net/dpaa2/dpaa2_ethdev.h | 997 +- drivers/net/dpaa2/dpaa2_flow.c | 8426 ++++++++--------- drivers/net/dpaa2/dpaa2_meter.c | 584 ++ drivers/net/dpaa2/dpaa2_parse_dump.h | 707 +- drivers/net/dpaa2/dpaa2_parser_decode.h | 1148 +++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 34 +- drivers/net/dpaa2/dpaa2_ptp.c | 177 +- drivers/net/dpaa2/dpaa2_recycle.c | 18 +- drivers/net/dpaa2/dpaa2_rxtx.c | 2818 +++--- drivers/net/dpaa2/dpaa2_sparser.c | 137 - drivers/net/dpaa2/dpaa2_sparser.h | 202 - drivers/net/dpaa2/mc/dpni.c | 127 +- drivers/net/dpaa2/mc/fsl_dpni.h | 378 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 30 +- drivers/net/dpaa2/mc/fsl_net.h | 4 +- drivers/net/dpaa2/meson.build | 3 +- drivers/net/dpaa2/rte_pmd_dpaa2.h | 238 +- lib/eventdev/eventdev_pmd.h | 9 +- 51 files changed, 14514 insertions(+), 11029 deletions(-) create mode 100644 drivers/common/dpaax/dpaax_devarg.h create mode 100644 drivers/event/dpaa2/dpaa2_scheduler.c delete mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni.c create mode 100644 drivers/net/dpaa2/dpaa2_meter.c create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v4-S3 01/65] net/dpaa2: refactor and optimize Rx parser result decode 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 02/65] net/dpaa2: generate devargs table and string from one list Prashant Gupta ` (63 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Hemant Agrawal From: Jun Yang <jun.yang@nxp.com> The hardware annotation (parse result) decode logic was scattered in dpaa2_rxtx.c and dpaa2_parse_dump.h, mixing the fast-path parsing with debug/print helpers and making the code hard to reuse and maintain. Move the frame annotation and parse-result decode helpers into a new dedicated header, dpaa2_parser_decode.h, and clean up the surrounding Rx path: - Add dpaa2_parser_decode.h with the annotation/parse-result decode helpers, taking the annotation as a const pointer so callers cannot mutate the hardware annotation area. - Replace the compile-time/static print path with a runtime devarg "drv_rx_print_parser_result", so the parser result dump can be enabled per device without rebuilding. - Pass the soft parser protocol (priv->sp_protocol) into the decode helpers so soft parser (SP) and VLAN/checksum handling is correct. - Use rte_memcpy / rte_cpu_to_be_64 consistently and tidy up the log messages. Optimize dpaa2_dev_rx_parse_new(): - Precompute the common "ETH + L3 + L4" packet types as DPAA2_FAST_PATH_PTYPE_ETH_IPV4[_UDP/_TCP] / _IPV6[...] macros and use them in the switch, instead of OR-ing RTE_PTYPE_* flags at runtime for every frame. - Reorder the switch cases so the most common traffic (IPv4/IPv6 UDP/TCP) is matched first, reducing branch cost on the hot path. - Keep VLAN frames on the fast path: read the FRC parse summary through a union (dpaa2_psr_summary), mask off the VLAN bit, and resolve the packet type via the fast-path switch plus dpaa2_dev_rx_parse_vlan(). Previously a VLAN tag made the frame miss the switch and fall into the slow path (dpaa2_dev_rx_parse_slow) for every packet; now the slow/FRC path is only used for the uncommon default case. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- doc/guides/nics/dpaa2.rst | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 31 +- drivers/net/dpaa2/dpaa2_ethdev.h | 173 ++-- drivers/net/dpaa2/dpaa2_parse_dump.h | 707 +++++++------- drivers/net/dpaa2/dpaa2_parser_decode.h | 1139 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 17 +- drivers/net/dpaa2/dpaa2_rxtx.c | 326 ++++--- drivers/net/dpaa2/rte_pmd_dpaa2.h | 13 +- 8 files changed, 1826 insertions(+), 586 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index 2928575208..60ca695f59 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -1,5 +1,5 @@ .. SPDX-License-Identifier: BSD-3-Clause - Copyright 2016,2020-2021 NXP + Copyright 2016,2020-2026 NXP DPAA2 Poll Mode Driver @@ -484,6 +484,10 @@ Refer to the document :doc:`build_and_test` for details. to start dropping the error packets in hardware (parse errors). e.g. ``fslmc:dpni.1,drv_rx_parse_drop=1`` +* Use dev arg option ``drv_rx_print_parser_result=1`` print detailed hardware + parser result of every received packet (debug only, hurts Rx performance). + e.g. ``fslmc:dpni.1,drv_rx_print_parser_result=1`` + * Use dev arg option ``drv_error_queue=1`` to enable Packets in Error queue. DPAA2 hardware drops the error packet in hardware. This option enables the hardware to not drop the error packet and let the driver dump the error diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 6afd641709..e69dc5b9a2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP */ #include <time.h> @@ -36,6 +36,7 @@ #define DRIVER_NO_PREFETCH_MODE "drv_no_prefetch" #define DRIVER_TX_CONF "drv_tx_conf" #define DRIVER_RX_PARSE_ERR_DROP "drv_rx_parse_drop" +#define DRIVER_RX_PRINT_PARSER_RESULT "drv_rx_print_parser_result" #define DRIVER_ERROR_QUEUE "drv_err_queue" #define DRIVER_NO_TAILDROP "drv_no_taildrop" #define DRIVER_NO_DATA_STASHING "drv_no_data_stashing" @@ -68,16 +69,13 @@ static uint64_t dev_tx_offloads_sup = RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; /* Tx offloads which cannot be disabled */ -static uint64_t dev_tx_offloads_nodis = - RTE_ETH_TX_OFFLOAD_MULTI_SEGS; +static uint64_t dev_tx_offloads_nodis = RTE_ETH_TX_OFFLOAD_MULTI_SEGS; /* enable timestamp in mbuf */ bool dpaa2_enable_ts[RTE_MAX_ETHPORTS]; uint64_t dpaa2_timestamp_rx_dynflag; int dpaa2_timestamp_dynfield_offset = -1; -bool dpaa2_print_parser_result; - /* Rx descriptor limit when DPNI loads PFDRs in PEB */ #define MAX_NB_RX_DESC_IN_PEB 11264 static int total_nb_rx_desc; @@ -3450,10 +3448,10 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) PMD_INIT_FUNC_TRACE(); - dpni_dev = rte_malloc(NULL, sizeof(struct fsl_mc_io), 0); + dpni_dev = rte_zmalloc(NULL, sizeof(struct fsl_mc_io), 0); if (!dpni_dev) { DPAA2_PMD_ERR("Memory allocation failed for dpni device"); - return -1; + return -ENOMEM; } dpni_dev->regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); eth_dev->process_private = dpni_dev; @@ -3502,9 +3500,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) hw_id = dpaa2_dev->object_id; ret = dpni_open(dpni_dev, CMD_PRI_LOW, hw_id, &priv->token); if (ret) { - DPAA2_PMD_ERR( - "Failure in opening dpni@%d with err code %d", - hw_id, ret); + DPAA2_PMD_ERR("Failure in opening dpni@%d with err code %d", + hw_id, ret); rte_free(dpni_dev); return ret; } @@ -3516,20 +3513,19 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) ret = dpni_reset(dpni_dev, CMD_PRI_LOW, priv->token); if (ret) { DPAA2_PMD_ERR("Failure cleaning dpni@%d with err code %d", - hw_id, ret); + hw_id, ret); goto init_err; } ret = dpni_get_attributes(dpni_dev, CMD_PRI_LOW, priv->token, &attr); if (ret) { - DPAA2_PMD_ERR( - "Failure in get dpni@%d attribute, err code %d", - hw_id, ret); + DPAA2_PMD_ERR("Failure in get dpni@%d attribute, err code %d", + hw_id, ret); goto init_err; } ret = dpni_get_api_version(dpni_dev, CMD_PRI_LOW, &priv->dpni_ver_major, - &priv->dpni_ver_minor); + &priv->dpni_ver_minor); if (ret) { DPAA2_PMD_ERR("Failure in get dpni@%d API version, err code %d", hw_id, ret); @@ -3590,8 +3586,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) DPAA2_PMD_INFO("Drop parse error packets in hw"); } - if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + if (dpaa2_get_devargs(dev->devargs, DRIVER_RX_PRINT_PARSER_RESULT)) + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); @@ -3993,6 +3989,7 @@ RTE_PMD_REGISTER_PARAM_STRING(NET_DPAA2_PMD_DRIVER_NAME, DRIVER_NO_PREFETCH_MODE "=<int>" DRIVER_TX_CONF "=<int>" DRIVER_RX_PARSE_ERR_DROP "=<int>" + DRIVER_RX_PRINT_PARSER_RESULT "=<int>" DRIVER_ERROR_QUEUE "=<int>" DRIVER_NO_TAILDROP "=<int>" DRIVER_NO_DATA_STASHING "=<int>"); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index d467e7b695..5b51414000 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" +#include "dpaa2_parse_dump.h" #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -102,6 +104,8 @@ #define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) + /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,43 +128,78 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4_EXT \ + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT \ + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_FRAG \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_FRAG \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_FRAG) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_FRAG) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ESP \ - (0x0005 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ESP \ - (0x0005 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_GTPU \ - (0x0014 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_GTPU \ - (0x0014 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_GTPC \ - (0x0015 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_GTPC \ - (0x0015 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -195,7 +234,17 @@ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; -extern bool dpaa2_print_parser_result; +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ @@ -270,42 +319,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -459,6 +472,7 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -467,6 +481,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -495,6 +510,42 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + uint32_t i, tc, flow; + struct dpaa2_queue *rxq; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + flow = m->hash.fdir.hi & RTE_DPAA2_MBUF_F_RX_FDIR_FLOW_MASK; + tc = m->hash.fdir.hi >> RTE_DPAA2_MBUF_F_RX_FDIR_TC_OFFSET; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (!rxq) + continue; + if (rxq->tc_index == tc && rxq->flow_id == flow) { + dpaa2_dump_print("Directed to TC%d-flow%d(rxq%d)\r\n", + tc, flow, i); + break; + } + } + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + dpaa2_dump_print("Balanced with hash(0x%08x)\r\n", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h index bcab3bf0cb..3ec9112ec9 100644 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ b/drivers/net/dpaa2/dpaa2_parse_dump.h @@ -1,374 +1,407 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2022 NXP + * Copyright 2022-2026 NXP * */ #ifndef _DPAA2_PARSE_DUMP_H #define _DPAA2_PARSE_DUMP_H -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> +#include "dpaa2_parser_decode.h" +#include "dpaa2_pmd_logs.h" -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; + dpaa2_dump_print("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + dpaa2_dump_print("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + dpaa2_dump_print("0x%02x ", psr->word8.rocev2.dest_qp[i]); -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; + dpaa2_dump_print("\r\n"); +} -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + dpaa2_dump_print("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + dpaa2_dump_print("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + dpaa2_dump_print("VXLAN inner eth:\r\n"); + dpaa2_dump_print("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + dpaa2_dump_print(":"); + dpaa2_dump_print("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); } -}; + dpaa2_dump_print("\r\n"); + dpaa2_dump_print("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + dpaa2_dump_print(":"); + dpaa2_dump_print("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + dpaa2_dump_print("\r\n"); + dpaa2_dump_print("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + dpaa2_dump_print("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) { - uint8_t ecpri_type; + uint8_t msg_type; struct rte_ecpri_combined_msg_hdr ecpri_msg; - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + dpaa2_dump_print("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } + dpaa2_dump_print("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + dpaa2_dump_print("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + dpaa2_dump_print("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + dpaa2_dump_print("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + dpaa2_dump_print("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + dpaa2_dump_print(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + dpaa2_dump_print("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + dpaa2_dump_print("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + dpaa2_dump_print("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + dpaa2_dump_print(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); } } static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) +dpaa2_print_fd_frc(const struct qbman_fd *fd) { - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + dpaa2_dump_print("FRC faicfdv: %d\r\n", frc->faicfdv); + dpaa2_dump_print("FRC faswov: %d\r\n", frc->faswov); + dpaa2_dump_print("FRC faiadv: %d\r\n", frc->faiadv); + dpaa2_dump_print("FRC faprv: %d\r\n", frc->faprv); + dpaa2_dump_print("FRC faeadv: %d\r\n", frc->faeadv); + dpaa2_dump_print("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + dpaa2_dump_print("FRC Check sum err: %d\r\n", sum->checksum_err); + dpaa2_dump_print("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + dpaa2_dump_print("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + dpaa2_dump_print("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } + l4_nm = ""; + dpaa2_dump_print("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); } - if (ecpri) - dpaa2_print_ecpri(fapr); + dpaa2_dump_print("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); } static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) { - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + dpaa2_dump_print("FAS discard\r\n"); + if (fas->macsec) + dpaa2_dump_print("FAS MACSEC present\r\n"); + if (fas->ptp) + dpaa2_dump_print("FAS PTP present\r\n"); + if (fas->multicast) + dpaa2_dump_print("FAS Multicast present\r\n"); + if (fas->broadcast) + dpaa2_dump_print("FAS Broadcast present\r\n"); + if (fas->kse) + dpaa2_dump_print("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + dpaa2_dump_print("FAS extract out of frame header\r\n"); + if (fas->mnle) + dpaa2_dump_print("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + dpaa2_dump_print("FAS Invalid table ID\r\n"); + if (fas->piee) + dpaa2_dump_print("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + dpaa2_dump_print("FAS Frame Length Error\r\n"); + if (fas->fpe) + dpaa2_dump_print("FAS Frame physical Error\r\n"); + if (fas->pte) + dpaa2_dump_print("FAS Parser terminate early\r\n"); + if (fas->isp) + dpaa2_dump_print("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + dpaa2_dump_print("FAS Error during parsing\r\n"); + if (fas->ble) + dpaa2_dump_print("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + dpaa2_dump_print("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + dpaa2_dump_print("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + dpaa2_dump_print("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + dpaa2_dump_print("FAS L4 checksum error detected\r\n"); + dpaa2_dump_print("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + dpaa2_dump_print("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + dpaa2_dump_print("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + dpaa2_dump_print("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + dpaa2_dump_print("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + dpaa2_dump_print("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + dpaa2_dump_print("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + dpaa2_dump_print("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + dpaa2_dump_print("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + dpaa2_dump_print("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + dpaa2_dump_print("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + dpaa2_dump_print("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + dpaa2_dump_print("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + dpaa2_dump_print("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + dpaa2_dump_print("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + dpaa2_dump_print("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + dpaa2_dump_print("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + dpaa2_dump_print("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + dpaa2_dump_print("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + dpaa2_dump_print("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + dpaa2_dump_print("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + dpaa2_dump_print("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + dpaa2_dump_print("FAF L2 soft parser error detected\r\n"); + + dpaa2_dump_print("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + dpaa2_dump_print("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + dpaa2_dump_print("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + dpaa2_dump_print("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + dpaa2_dump_print("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + dpaa2_dump_print("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + dpaa2_dump_print("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + dpaa2_dump_print("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + dpaa2_dump_print("FAFE TUNNEL TCP present\r\n"); } + } else { + dpaa2_dump_print("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); } - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + dpaa2_dump_print("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + dpaa2_dump_print("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + dpaa2_dump_print("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + dpaa2_dump_print("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + dpaa2_dump_print("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + dpaa2_dump_print("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + dpaa2_dump_print("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + dpaa2_dump_print("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + dpaa2_dump_print("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + dpaa2_dump_print("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + dpaa2_dump_print("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + dpaa2_dump_print("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + dpaa2_dump_print("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + dpaa2_dump_print("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + dpaa2_dump_print("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + dpaa2_dump_print("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + dpaa2_dump_print("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + dpaa2_dump_print("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + dpaa2_dump_print("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + dpaa2_dump_print("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + dpaa2_dump_print("FAF UDP Present\r\n"); + + dpaa2_dump_print("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + dpaa2_dump_print("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + dpaa2_dump_print("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + dpaa2_dump_print("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + dpaa2_dump_print("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + dpaa2_dump_print("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + dpaa2_dump_print("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); } - dpaa2_print_faf(&fapr); } - -#endif +#endif /* _DPAA2_PARSE_DUMP_H */ diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..f07a70a826 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1139 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSER_DECODE_H +#define _DPAA2_PARSER_DECODE_H + +#define DPAA2_BIT_SIZE(t) (sizeof(t) * 8) +#define DPAA2_BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define DPAA2_BIT_LAST_OFFSET(t) (DPAA2_BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + uint32_t idx; + + if (!fafe.fafe_8b) + return UINT32_MAX; + idx = rte_bsf32(fafe.fafe_8b); + return (DPAA2_BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b) - idx) + + DPAA2_BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b tmp; + uint32_t idx; + + tmp.faf_l = *faf_l; + if (!tmp.faf_l_32b) + return UINT32_MAX; + idx = rte_bsf32(tmp.faf_l_32b); + return (DPAA2_BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b) - idx) + + DPAA2_BIT_OFFSET(struct dpaa2_psr_result_parse, word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b tmp; + uint32_t idx; + + tmp.faf_h = *faf_h; + if (!tmp.faf_h_64b) + return UINT32_MAX; + idx = rte_bsf64(tmp.faf_h_64b); + return (DPAA2_BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b) - idx) + + DPAA2_BIT_OFFSET(struct dpaa2_psr_result_parse, word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + return -ENOTSUP; + } + + if (*bit_offset == UINT32_MAX) + return -EINVAL; + + return 0; +} + +static inline void __rte_hot +dpaa2_dev_rx_parse_vlan(struct rte_mbuf *m, uint32_t *packet_type, + const struct dpaa2_psr_summary *sum, + const struct dpaa2_annot_hdr *annotation) +{ + union { + uint64_t word5; + struct dpaa2_psr_result_word5 psr_word5; + } word5_u; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + word5_u.word5 = rte_cpu_to_be_64(annotation->word5); + *packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = word5_u.psr_word5.vlan_tci_n_off; + *packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = word5_u.psr_word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); +} + +#define ECPRI(type) (void)(type) +#define ROCEv2(type) (void)(type) + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const void *fd_frc, struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation, bool sp) +{ + const struct dpaa2_ingress_frc *frc = fd_frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_UNKNOWN; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) + dpaa2_dev_rx_parse_vlan(m, &packet_type, sum, annotation); + + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + /* Non-VLAN IP frames need RTE_PTYPE_L2_ETHER; VLAN frames + * already have L2_ETHER_VLAN set above. + */ + if (ip4_6 && !sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_L4_UDP | RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } else { + packet_type |= RTE_PTYPE_L4_NONFRAG; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (!sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + if (!sp) + goto final_type; + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (sum->fafe0) { + ECPRI(packet_type); + } else if (sum->fafe1) { + ROCEv2(packet_type); + } else if (vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } else if (!vxlan && sum->fafe2) { + packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + +final_type: + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + /** Must mask as 0xff to specify type.*/ + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) + return -ENOTSUP; + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + return -ENOTSUP; + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + return -ENOTSUP; + } + + return extract_nb; +} +#endif /* _DPAA2_PARSER_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..8b699bb5af 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -1,10 +1,17 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017 NXP + * Copyright 2017-2026 NXP */ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,12 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +static inline __rte_format_printf(1, 2) void +dpaa2_dump_print(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + rte_vlog(RTE_LOG_NOTICE, RTE_LOGTYPE_USER1, fmt, ap); + va_end(ap); +} #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index df3eefc134..d3512d56f9 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2026 NXP * */ @@ -26,13 +26,18 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" - -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); - -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; +#include "dpaa2_parser_decode.h" + +#define DPAA2_FAST_PATH_PTYPE_ETH_IPV4 (RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4) +#define DPAA2_FAST_PATH_PTYPE_ETH_IPV6 (RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6) +#define DPAA2_FAST_PATH_PTYPE_ETH_IPV4_UDP \ + (DPAA2_FAST_PATH_PTYPE_ETH_IPV4 | RTE_PTYPE_L4_UDP) +#define DPAA2_FAST_PATH_PTYPE_ETH_IPV6_UDP \ + (DPAA2_FAST_PATH_PTYPE_ETH_IPV6 | RTE_PTYPE_L4_UDP) +#define DPAA2_FAST_PATH_PTYPE_ETH_IPV4_TCP \ + (DPAA2_FAST_PATH_PTYPE_ETH_IPV4 | RTE_PTYPE_L4_TCP) +#define DPAA2_FAST_PATH_PTYPE_ETH_IPV6_TCP \ + (DPAA2_FAST_PATH_PTYPE_ETH_IPV6 | RTE_PTYPE_L4_TCP) static inline rte_mbuf_timestamp_t * dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) @@ -51,128 +56,107 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) +static inline void +dpaa2_dev_rx_mbuf_flc_offload(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->hash.fdir.hi = (tc << RTE_DPAA2_MBUF_F_RX_FDIR_TC_OFFSET) | flow; + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d].flow%d", tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", m->hash.rss); + } +} +static inline void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + union { + uint16_t u16; + struct dpaa2_psr_summary sum; + } frc_u; + struct dpaa2_psr_summary *frc_parse = &frc_u.sum; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false; + + frc_u.u16 = DPAA2_GET_FD_FRC_PARSE_SUM(fd); m->packet_type = RTE_PTYPE_UNKNOWN; - switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; + if (unlikely(is_vlan)) + frc_u.u16 &= (~DPAA2_PKT_TYPE_VLAN); + switch (frc_u.u16) { + case DPAA2_PKT_TYPE_IPV4_UDP: + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + case DPAA2_PKT_TYPE_IPV4: + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV6_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV4_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_IPV6_TCP: + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV6_TCP; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_IPV6: + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV6; break; case DPAA2_PKT_TYPE_IPV4_FRAG: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV4 | RTE_PTYPE_L4_FRAG; break; case DPAA2_PKT_TYPE_IPV6_FRAG: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV6 | RTE_PTYPE_L4_FRAG; break; case DPAA2_PKT_TYPE_IPV4_ESP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV4 | RTE_PTYPE_TUNNEL_ESP; break; case DPAA2_PKT_TYPE_IPV6_ESP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV6 | RTE_PTYPE_TUNNEL_ESP; break; case DPAA2_PKT_TYPE_IPV4_GTPU: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | - RTE_PTYPE_TUNNEL_GTPU; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV4_UDP | RTE_PTYPE_TUNNEL_GTPU; break; case DPAA2_PKT_TYPE_IPV6_GTPU: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | - RTE_PTYPE_TUNNEL_GTPU; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV6_UDP | RTE_PTYPE_TUNNEL_GTPU; break; case DPAA2_PKT_TYPE_IPV4_GTPC: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | - RTE_PTYPE_TUNNEL_GTPC; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV4_UDP | RTE_PTYPE_TUNNEL_GTPC; break; case DPAA2_PKT_TYPE_IPV6_GTPC: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | - RTE_PTYPE_TUNNEL_GTPC; + m->packet_type = DPAA2_FAST_PATH_PTYPE_ETH_IPV6_UDP | RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); - } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - m->ol_flags |= RTE_MBUF_F_RX_FDIR; - m->hash.fdir.hi = (tc << 16) | flow; - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + m->packet_type = dpaa2_dev_rx_parse_frc(&fd->simple.frc, m, + annotation, priv->sp_protocol); + default_parsed = true; } + if (unlikely(is_vlan && !default_parsed)) + dpaa2_dev_rx_parse_vlan(m, &m->packet_type, frc_parse, annotation); + if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", + DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", *dpaa2_timestamp_dynfield(m)); } - DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " - "ol_flags =0x%" PRIx64 "", - frc, m->packet_type, m->ol_flags); + DPAA2_PMD_DP_DEBUG("HW frc = 0x%x packet type = 0x%x ol_flags = 0x%lx", + frc_u.u16, m->packet_type, m->ol_flags); } static inline uint32_t __rte_hot @@ -277,13 +261,15 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); + annotation->word4); + + RTE_SET_USED(priv); if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; @@ -295,9 +281,6 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); - if (dpaa2_enable_ts[mbuf->port]) { *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; @@ -306,27 +289,23 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ switch (annotation->word4) { case DPAA2_L3_IPv4: - return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4; + return DPAA2_FAST_PATH_PTYPE_ETH_IPV4; case DPAA2_L3_IPv6: - return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; + return DPAA2_FAST_PATH_PTYPE_ETH_IPV6; case DPAA2_L3_IPv4_TCP: - return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | - RTE_PTYPE_L4_TCP; + return DPAA2_FAST_PATH_PTYPE_ETH_IPV4_TCP; case DPAA2_L3_IPv4_UDP: - return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | - RTE_PTYPE_L4_UDP; + return DPAA2_FAST_PATH_PTYPE_ETH_IPV4_UDP; case DPAA2_L3_IPv6_TCP: - return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | - RTE_PTYPE_L4_TCP; + return DPAA2_FAST_PATH_PTYPE_ETH_IPV6_TCP; case DPAA2_L3_IPv6_UDP: - return RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | - RTE_PTYPE_L4_UDP; + return DPAA2_FAST_PATH_PTYPE_ETH_IPV6_UDP; default: break; } @@ -335,15 +314,18 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; - int i = 0; + int i = 0, is_vlan = false; void *hw_annot_addr; struct rte_mbuf *first_seg, *next_seg, *cur_seg, *temp; + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & DPAA2_PKT_TYPE_VLAN))) + is_vlan = true; + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); @@ -364,33 +346,32 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; + first_seg->port = priv->eth_dev->data->port_id; if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, is_vlan); else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, hw_annot_addr); + dpaa2_dev_rx_mbuf_flc_offload(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG rte_mempool_check_cookies(rte_mempool_from_obj((void *)first_seg), - (void **)&first_seg, 1, 1); + (void **)&first_seg, 1, 1); #endif cur_seg = first_seg; while (!DPAA2_SG_IS_FINAL(sge) && i < DPAA2_MAX_SGS) { sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR( - DPAA2_GET_FLE_ADDR(sge)); + sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); next_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, rte_dpaa2_bpid_info[DPAA2_GET_FLE_BPID(sge)].meta_data_size); - next_seg->buf_addr = (uint8_t *)sg_addr; - next_seg->data_off = DPAA2_GET_FLE_OFFSET(sge); - next_seg->data_len = sge->length & 0x1FFFF; - first_seg->nb_segs += 1; + next_seg->buf_addr = (uint8_t *)sg_addr; + next_seg->data_off = DPAA2_GET_FLE_OFFSET(sge); + next_seg->data_len = sge->length & 0x1FFFF; + first_seg->nb_segs++; rte_mbuf_refcnt_set(next_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG rte_mempool_check_cookies(rte_mempool_from_obj((void *)next_seg), - (void **)&next_seg, 1, 1); + (void **)&next_seg, 1, 1); #endif cur_seg->next = next_seg; next_seg->next = NULL; @@ -400,8 +381,8 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); rte_mbuf_refcnt_set(temp, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 1); + rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), + (void **)&temp, 1, 1); #endif rte_pktmbuf_free_seg(temp); @@ -409,13 +390,20 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & DPAA2_PKT_TYPE_VLAN))) { + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -425,13 +413,13 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf), - (void **)&mbuf, 1, 1); + (void **)&mbuf, 1, 1); #endif /* Parse the packet */ @@ -441,9 +429,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_flc_offload(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -702,6 +691,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -758,14 +748,11 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) fas = hw_annot_addr; if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -820,18 +807,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -937,18 +918,13 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1017,7 +993,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1042,7 +1021,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1069,7 +1051,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1179,12 +1164,11 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1192,6 +1176,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1343,6 +1328,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1364,7 +1350,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1645,8 +1631,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index 237c3cd6e7..83bee098bc 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2024 NXP + * Copyright 2018-2026 NXP */ #ifndef _RTE_PMD_DPAA2_H @@ -14,6 +14,17 @@ #include <rte_compat.h> #include <rte_flow.h> +/** + * LX series support only. + * if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + * tc = (m->hash.fdir.hi >> RTE_DPAA2_MBUF_F_RX_FDIR_TC_OFFSET); + * flow = m->hash.fdir.hi & RTE_DPAA2_MBUF_F_RX_FDIR_FLOW_MASK; + * } + */ +#define RTE_DPAA2_MBUF_F_RX_FDIR_TC_OFFSET 16 +#define RTE_DPAA2_MBUF_F_RX_FDIR_FLOW_MASK \ + ((UINT32_C(1) << RTE_DPAA2_MBUF_F_RX_FDIR_TC_OFFSET) - 1) + /** * Create a flow rule to demultiplex ethernet traffic to separate network * interfaces. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 02/65] net/dpaa2: generate devargs table and string from one list 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 01/65] net/dpaa2: refactor and optimize Rx parser result decode Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 03/65] crypto/dpaa2_sec: use table-driven devargs parsing Prashant Gupta ` (62 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add a common dpaax_devarg.h header providing the dpaax_devargs type, the dpaax_get_devargs() parse helper, and two X-macro operators: DPAAX_DEVARG_TABLE_ENTRY(key, handle, flag) -> {key, handle, flag}, DPAAX_DEVARG_STRING_ENTRY(key, handle, flag) -> key "=<int> " Convert the dpaa2 net driver to declare its device arguments once via a single DPAA2_DEVARGS(ENTRY) list. The same list now builds both the parse table (s_dpaa2_devargs) and the RTE_PMD_REGISTER_PARAM_STRING valid-args string, so every key is spelled exactly once. The per-arg string defines and the hand-written dpaa2_get_devargs()/ check_devargs_handler() lookups are replaced by a single dpaax_get_devargs() call that sets priv->flags. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/common/dpaax/dpaax_devarg.h | 69 ++++++++++++ drivers/net/dpaa2/dpaa2_ethdev.c | 158 +++++++--------------------- 2 files changed, 106 insertions(+), 121 deletions(-) create mode 100644 drivers/common/dpaax/dpaax_devarg.h diff --git a/drivers/common/dpaax/dpaax_devarg.h b/drivers/common/dpaax/dpaax_devarg.h new file mode 100644 index 0000000000..2481a399f5 --- /dev/null +++ b/drivers/common/dpaax/dpaax_devarg.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2026 NXP + */ + +#ifndef _DPAAX_DEVARG_H_ +#define _DPAAX_DEVARG_H_ +#include <stdlib.h> +#include <rte_kvargs.h> +#include <ethdev_driver.h> + +struct dpaax_devargs { + const char *arg_key; + void (*handle)(void *vdev, const struct rte_kvargs_pair *pair); + uint64_t flag_bit; +}; + +/* Shared expansions for a driver's devargs X-macro list. + * + * A driver declares its argument list once as a list-macro that takes the + * per-entry operator as a parameter, for example: + * + * #define MY_DEVARGS(ENTRY) \ + * ENTRY("drv_foo", foo_handler, 0) \ + * ENTRY("drv_bar", NULL, MY_BAR_FLAG) + * + * The same list then generates both the parse table and the registered + * valid-args string by passing the matching operator below: + * + * static const struct dpaax_devargs s_my_devargs[] = { + * MY_DEVARGS(DPAAX_DEVARG_TABLE_ENTRY) + * }; + * RTE_PMD_REGISTER_PARAM_STRING(name, MY_DEVARGS(DPAAX_DEVARG_STRING_ENTRY)); + * + * This keeps each key spelled exactly once. + */ +#define DPAAX_DEVARG_TABLE_ENTRY(key, handle, flag) {key, handle, flag}, +#define DPAAX_DEVARG_STRING_ENTRY(key, handle, flag) key "=<int> " + +#define dpaax_get_devargs(dev_args, dev, flags) \ +({ \ + uint32_t arg_num = RTE_DIM(dev_args), arg_idx, kv_idx;\ + struct rte_device *rdev = dev->device; \ + struct rte_kvargs *kvlist = NULL; \ + struct rte_kvargs_pair *pair; \ + uint32_t flag_bit; \ + \ + if (rdev->devargs) \ + kvlist = rte_kvargs_parse(rdev->devargs->args, NULL); \ + if (kvlist) { \ + for (arg_idx = 0; arg_idx < arg_num; arg_idx++) { \ + for (kv_idx = 0; kv_idx < kvlist->count; kv_idx++) { \ + pair = &kvlist->pairs[kv_idx]; \ + if (strcmp(pair->key, dev_args[arg_idx].arg_key)) \ + continue; \ + if (dev_args[arg_idx].handle) \ + dev_args[arg_idx].handle(dev, pair); \ + flag_bit = dev_args[arg_idx].flag_bit; \ + if (flags && pair->value) { \ + if (atoi(pair->value)) \ + (*((uint32_t *)flags)) |= flag_bit; \ + else \ + (*((uint32_t *)flags)) &= ~flag_bit; \ + } \ + } \ + } \ + rte_kvargs_free(kvlist); \ + } \ +}) +#endif /* _DPAAX_DEVARG_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index e69dc5b9a2..cd39c7874e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -31,18 +31,32 @@ #include "dpaa2_ethdev.h" #include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> +#include <dpaax_devarg.h> + +/* Single source of truth for dpaa2 devargs: + * ENTRY(key-string, handle, flag-bit) + * handle is an optional per-arg callback (NULL if the arg only sets a flag). + * Both the parse table (s_dpaa2_devargs) and the registered valid-args + * string are generated from this list, so each key is spelled once. The + * ENTRY operator (table vs string form) is provided by dpaax_devarg.h. + */ +#define DPAA2_DEVARGS(ENTRY) \ + ENTRY("drv_loopback", NULL, DPAA2_RX_LOOPBACK_MODE) \ + ENTRY("drv_no_prefetch", NULL, DPAA2_NO_PREFETCH_RX) \ + ENTRY("drv_tx_conf", NULL, DPAA2_TX_CONF_ENABLE) \ + ENTRY("drv_rx_parse_drop", NULL, DPAA2_PARSE_ERR_DROP) \ + ENTRY("drv_rx_print_parser_result", NULL, DPAA2_RX_PRINT_PSR_RESULT_FLAG) \ + ENTRY("drv_err_queue", NULL, DPAA2_RX_ERROR_QUEUE_FLAG) \ + ENTRY("drv_no_taildrop", NULL, DPAA2_RX_TAILDROP_OFF) \ + ENTRY("drv_no_data_stashing", NULL, DPAA2_RX_DATA_STASHING_OFF_FLAG) -#define DRIVER_LOOPBACK_MODE "drv_loopback" -#define DRIVER_NO_PREFETCH_MODE "drv_no_prefetch" -#define DRIVER_TX_CONF "drv_tx_conf" -#define DRIVER_RX_PARSE_ERR_DROP "drv_rx_parse_drop" -#define DRIVER_RX_PRINT_PARSER_RESULT "drv_rx_print_parser_result" -#define DRIVER_ERROR_QUEUE "drv_err_queue" -#define DRIVER_NO_TAILDROP "drv_no_taildrop" -#define DRIVER_NO_DATA_STASHING "drv_no_data_stashing" #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_REPEAT_TIME 90 /* 9s (90 * 100ms) in total */ +static const struct dpaax_devargs s_dpaa2_devargs[] = { + DPAA2_DEVARGS(DPAAX_DEVARG_TABLE_ENTRY) +}; + /* Supported Rx offloads */ static uint64_t dev_rx_offloads_sup = RTE_ETH_RX_OFFLOAD_CHECKSUM | @@ -3398,47 +3412,9 @@ populate_mac_addr(struct fsl_mc_io *dpni_dev, return ret; } -static int -check_devargs_handler(__rte_unused const char *key, const char *value, - __rte_unused void *opaque) -{ - if (strcmp(value, "1")) - return -1; - - return 0; -} - -static int -dpaa2_get_devargs(struct rte_devargs *devargs, const char *key) -{ - struct rte_kvargs *kvlist; - - if (!devargs) - return 0; - - kvlist = rte_kvargs_parse(devargs->args, NULL); - if (!kvlist) - return 0; - - if (!rte_kvargs_count(kvlist, key)) { - rte_kvargs_free(kvlist); - return 0; - } - - if (rte_kvargs_process(kvlist, key, - check_devargs_handler, NULL) < 0) { - rte_kvargs_free(kvlist); - return 0; - } - rte_kvargs_free(kvlist); - - return 1; -} - static int dpaa2_dev_init(struct rte_eth_dev *eth_dev) { - struct rte_device *dev = eth_dev->device; struct rte_dpaa2_device *dpaa2_dev; struct fsl_mc_io *dpni_dev; struct dpni_attr attr; @@ -3456,42 +3432,23 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) dpni_dev->regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); eth_dev->process_private = dpni_dev; - /* RX no prefetch mode? */ - if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_PREFETCH_MODE)) { - priv->flags |= DPAA2_NO_PREFETCH_RX; - DPAA2_PMD_INFO("No RX prefetch mode"); - } - - if (dpaa2_get_devargs(dev->devargs, DRIVER_LOOPBACK_MODE)) { - priv->flags |= DPAA2_RX_LOOPBACK_MODE; - DPAA2_PMD_INFO("Rx loopback mode"); - } - - if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_TAILDROP)) { - priv->flags |= DPAA2_RX_TAILDROP_OFF; - DPAA2_PMD_INFO("Rx taildrop disabled"); - } + priv->flags = 0; + dpaax_get_devargs(s_dpaa2_devargs, eth_dev, &priv->flags); - if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || - getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; - DPAA2_PMD_INFO("Data stashing disabled"); - } + eth_dev->dev_ops = &dpaa2_ethdev_ops; + eth_dev->rx_queue_count = dpaa2_dev_rx_queue_count; + if (priv->flags & DPAA2_RX_LOOPBACK_MODE) + eth_dev->rx_pkt_burst = dpaa2_dev_loopback_rx; + else if (priv->flags & DPAA2_NO_PREFETCH_RX) + eth_dev->rx_pkt_burst = dpaa2_dev_rx; + else + eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx; + eth_dev->tx_pkt_burst = dpaa2_dev_tx; /* For secondary processes, the primary has done all the work */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) { - /* In case of secondary, only burst and ops API need to be - * plugged. + /* In case of secondary, everything is done here. */ - eth_dev->dev_ops = &dpaa2_ethdev_ops; - eth_dev->rx_queue_count = dpaa2_dev_rx_queue_count; - if (priv->flags & DPAA2_RX_LOOPBACK_MODE) - eth_dev->rx_pkt_burst = dpaa2_dev_loopback_rx; - else if (priv->flags & DPAA2_NO_PREFETCH_RX) - eth_dev->rx_pkt_burst = dpaa2_dev_rx; - else - eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx; - eth_dev->tx_pkt_burst = dpaa2_dev_tx; return 0; } @@ -3564,30 +3521,10 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->options = attr.options; priv->max_mac_filters = attr.mac_filter_entries; priv->max_vlan_filters = attr.vlan_filter_entries; - priv->flags = 0; #if defined(RTE_LIBRTE_IEEE1588) DPAA2_PMD_INFO("DPDK IEEE1588 is enabled"); priv->flags |= DPAA2_TX_CONF_ENABLE; #endif - /* Used with ``fslmc:dpni.1,drv_tx_conf=1`` */ - if (dpaa2_get_devargs(dev->devargs, DRIVER_TX_CONF)) { - priv->flags |= DPAA2_TX_CONF_ENABLE; - DPAA2_PMD_INFO("TX_CONF Enabled"); - } - - if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; - DPAA2_PMD_INFO("Enable error queue"); - } - - /* Packets with parse error to be dropped in hw */ - if (dpaa2_get_devargs(dev->devargs, DRIVER_RX_PARSE_ERR_DROP)) { - priv->flags |= DPAA2_PARSE_ERR_DROP; - DPAA2_PMD_INFO("Drop parse error packets in hw"); - } - - if (dpaa2_get_devargs(dev->devargs, DRIVER_RX_PRINT_PARSER_RESULT)) - priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); @@ -3666,20 +3603,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } - eth_dev->dev_ops = &dpaa2_ethdev_ops; - eth_dev->rx_queue_count = dpaa2_dev_rx_queue_count; - - if (dpaa2_get_devargs(dev->devargs, DRIVER_LOOPBACK_MODE)) { - eth_dev->rx_pkt_burst = dpaa2_dev_loopback_rx; - DPAA2_PMD_INFO("Loopback mode"); - } else if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_PREFETCH_MODE)) { - eth_dev->rx_pkt_burst = dpaa2_dev_rx; - DPAA2_PMD_INFO("No Prefetch mode"); - } else { - eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx; - } - eth_dev->tx_pkt_burst = dpaa2_dev_tx; - /* Init fields w.r.t. classification */ memset(&priv->extract.qos_key_extract, 0, sizeof(struct dpaa2_key_extract)); @@ -3704,8 +3627,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } ret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token, - RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN - + VLAN_TAG_SIZE); + RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN + VLAN_TAG_SIZE); if (ret) { DPAA2_PMD_ERR("Unable to set mtu. check config"); goto init_err; @@ -3985,12 +3907,6 @@ static struct rte_dpaa2_driver rte_dpaa2_pmd = { RTE_PMD_REGISTER_DPAA2(NET_DPAA2_PMD_DRIVER_NAME, rte_dpaa2_pmd); RTE_PMD_REGISTER_PARAM_STRING(NET_DPAA2_PMD_DRIVER_NAME, - DRIVER_LOOPBACK_MODE "=<int> " - DRIVER_NO_PREFETCH_MODE "=<int>" - DRIVER_TX_CONF "=<int>" - DRIVER_RX_PARSE_ERR_DROP "=<int>" - DRIVER_RX_PRINT_PARSER_RESULT "=<int>" - DRIVER_ERROR_QUEUE "=<int>" - DRIVER_NO_TAILDROP "=<int>" - DRIVER_NO_DATA_STASHING "=<int>"); + DPAA2_DEVARGS(DPAAX_DEVARG_STRING_ENTRY) +); RTE_LOG_REGISTER_DEFAULT(dpaa2_logtype_pmd, NOTICE); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 03/65] crypto/dpaa2_sec: use table-driven devargs parsing 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 01/65] net/dpaa2: refactor and optimize Rx parser result decode Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 02/65] net/dpaa2: generate devargs table and string from one list Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 04/65] dma/dpaa2: " Prashant Gupta ` (61 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Convert the dpaa2_sec devargs handling to the shared dpaax_devargs table so each argument key is declared once and drives both the parse table and the registered valid-args string. Replace the custom check_devargs_handler()/dpaa2_sec_get_devargs() pair with the generic dpaax_get_devargs() helper, and attach per-arg callbacks (dpaa2_sec_devarg_dump_set, dpaa2_sec_devarg_order_set) for the value-carrying arguments. Move the dump level out of the global dpaa2_sec_dp_dump variable into the per-device private data (priv->dump_level) so the dump setting is scoped per device instead of being process-global, and move the dpaa2_sec_dump_levels enum into dpaa2_sec_priv.h. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 133 ++++++++------------ drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 10 +- 2 files changed, 61 insertions(+), 82 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 3d980d096f..6e759dd821 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ @@ -31,6 +31,7 @@ #include <fsl_dpseci.h> #include <fsl_mc_sys.h> #include <rte_hexdump.h> +#include <dpaax_devarg.h> #include "dpaa2_sec_priv.h" #include "dpaa2_sec_event.h" @@ -55,18 +56,40 @@ #define DPAA2_DEFAULT_NAT_T_PORT 4500 #define NO_PREFETCH 0 -#define DRIVER_DUMP_MODE "drv_dump_mode" -#define DRIVER_STRICT_ORDER "drv_strict_order" +static void +dpaa2_sec_devarg_order_set(void *vdev, const struct rte_kvargs_pair *pair) +{ + struct rte_cryptodev *dev = vdev; + struct dpaa2_sec_dev_private *priv = dev->data->dev_private; + + priv->en_loose_ordered = atoi(pair->value) ? false : true; +} + +static void +dpaa2_sec_devarg_dump_set(void *vdev, const struct rte_kvargs_pair *pair) +{ + struct rte_cryptodev *dev = vdev; + struct dpaa2_sec_dev_private *priv = dev->data->dev_private; + enum dpaa2_sec_dump_levels val; + + val = atoi(pair->value); + if (val > DPAA2_SEC_DP_FULL_DUMP) { + DPAA2_SEC_WARN("%s: val(%d) > full dump(%d), changing to full dump", + __func__, val, DPAA2_SEC_DP_FULL_DUMP); + val = DPAA2_SEC_DP_FULL_DUMP; + } + priv->dump_level = val; +} + +#define DPAA2_DEVARGS(ENTRY) \ + ENTRY("drv_dump_mode", dpaa2_sec_devarg_dump_set, 0) \ + ENTRY("drv_strict_order", dpaa2_sec_devarg_order_set, 0) -/* DPAA2_SEC_DP_DUMP levels */ -enum dpaa2_sec_dump_levels { - DPAA2_SEC_DP_NO_DUMP, - DPAA2_SEC_DP_ERR_DUMP, - DPAA2_SEC_DP_FULL_DUMP +static const struct dpaax_devargs s_dpaa2_sec_devargs[] = { + DPAA2_DEVARGS(DPAAX_DEVARG_TABLE_ENTRY) }; uint8_t cryptodev_driver_id; -uint8_t dpaa2_sec_dp_dump = DPAA2_SEC_DP_ERR_DUMP; static int s_dpaa2_sec_cntx_pos = -1; @@ -1701,10 +1724,9 @@ dpaa2_sec_fd_to_mbuf(const struct qbman_fd *fd, static void dpaa2_sec_dump(struct rte_crypto_op *op, FILE *f) { - int i; dpaa2_sec_session *sess = NULL; struct ctxt_priv *priv; - uint8_t bufsize; + uint8_t bufsize, i; struct rte_crypto_sym_op *sym_op; if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) @@ -1717,7 +1739,7 @@ dpaa2_sec_dump(struct rte_crypto_op *op, FILE *f) if (sess == NULL) goto mbuf_dump; - priv = (struct ctxt_priv *)sess->ctxt; + priv = sess->ctxt; fprintf(f, "\n****************************************\n" "session params:\n\tContext type:\t%d\n\tDirection:\t%s\n" "\tCipher alg:\t%d\n\tAuth alg:\t%d\n\tAead alg:\t%d\n" @@ -1746,7 +1768,7 @@ dpaa2_sec_dump(struct rte_crypto_op *op, FILE *f) sess->pdcp.hfn_threshold); #endif - bufsize = (uint8_t)priv->flc_desc[0].flc.word1_sdl; + bufsize = priv->flc_desc[0].flc.word1_sdl; fprintf(f, "Descriptor Dump:\n"); for (i = 0; i < bufsize; i++) fprintf(f, "\tDESC[%d]:0x%x\n", i, priv->flc_desc[0].desc[i]); @@ -1950,10 +1972,10 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, static uint16_t dpaa2_sec_dequeue_burst(void *qp, struct rte_crypto_op **ops, - uint16_t nb_ops) + uint16_t nb_ops) { /* Function is responsible to receive frames for a given device and VQ*/ - struct dpaa2_sec_qp *dpaa2_qp = (struct dpaa2_sec_qp *)qp; + struct dpaa2_sec_qp *dpaa2_qp = qp; struct qbman_result *dq_storage; uint32_t fqid = dpaa2_qp->rx_vq.fqid; int ret, num_rx = 0; @@ -1961,12 +1983,12 @@ dpaa2_sec_dequeue_burst(void *qp, struct rte_crypto_op **ops, struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; + struct dpaa2_sec_dev_private *priv = dpaa2_qp->rx_vq.crypto_data->dev_private; if (!DPAA2_PER_LCORE_DPIO) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_SEC_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_SEC_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } @@ -1976,18 +1998,15 @@ dpaa2_sec_dequeue_burst(void *qp, struct rte_crypto_op **ops, qbman_pull_desc_clear(&pulldesc); qbman_pull_desc_set_numframes(&pulldesc, - (nb_ops > dpaa2_dqrr_size) ? - dpaa2_dqrr_size : nb_ops); + (nb_ops > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_ops); qbman_pull_desc_set_fq(&pulldesc, fqid); qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (dma_addr_t)DPAA2_VADDR_TO_IOVA(dq_storage), - 1); + (dma_addr_t)DPAA2_VADDR_TO_IOVA(dq_storage), 1); /*Issue a volatile dequeue command. */ while (1) { if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_SEC_WARN( - "SEC VDQ command is not issued : QBMAN busy"); + DPAA2_SEC_WARN("SEC VDQ command is not issued : QBMAN busy"); /* Portal was busy, try again */ continue; } @@ -2017,8 +2036,7 @@ dpaa2_sec_dequeue_burst(void *qp, struct rte_crypto_op **ops, is_last = 1; /* Check for valid frame. */ status = (uint8_t)qbman_result_DQ_flags(dq_storage); - if (unlikely( - (status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) { + if (unlikely(!(status & QBMAN_DQ_STAT_VALIDFRAME))) { DPAA2_SEC_DP_DEBUG("No frame is delivered"); continue; } @@ -2029,10 +2047,9 @@ dpaa2_sec_dequeue_burst(void *qp, struct rte_crypto_op **ops, if (unlikely(fd->simple.frc)) { /* TODO Parse SEC errors */ - if (dpaa2_sec_dp_dump > DPAA2_SEC_DP_NO_DUMP) { - DPAA2_SEC_DP_ERR("SEC returned Error - %x", - fd->simple.frc); - if (dpaa2_sec_dp_dump > DPAA2_SEC_DP_ERR_DUMP) + if (priv->dump_level > DPAA2_SEC_DP_NO_DUMP) { + DPAA2_SEC_DP_ERR("SEC returned Error - %x", fd->simple.frc); + if (priv->dump_level > DPAA2_SEC_DP_ERR_DUMP) dpaa2_sec_dump(ops[num_rx], stdout); } @@ -2049,7 +2066,7 @@ dpaa2_sec_dequeue_burst(void *qp, struct rte_crypto_op **ops, dpaa2_qp->rx_vq.rx_pkts += num_rx; DPAA2_SEC_DP_DEBUG("SEC RX pkts %d err pkts %" PRIu64, num_rx, - dpaa2_qp->rx_vq.err_pkts); + dpaa2_qp->rx_vq.err_pkts); /*Return the total number of packets received to DPAA2 app*/ return num_rx; } @@ -4332,53 +4349,6 @@ dpaa2_sec_uninit(const struct rte_cryptodev *dev) return 0; } -static int -check_devargs_handler(const char *key, const char *value, - void *opaque) -{ - struct rte_cryptodev *dev = (struct rte_cryptodev *)opaque; - struct dpaa2_sec_dev_private *priv = dev->data->dev_private; - - if (!strcmp(key, "drv_strict_order")) { - priv->en_loose_ordered = false; - } else if (!strcmp(key, "drv_dump_mode")) { - dpaa2_sec_dp_dump = atoi(value); - if (dpaa2_sec_dp_dump > DPAA2_SEC_DP_FULL_DUMP) { - DPAA2_SEC_WARN("WARN: DPAA2_SEC_DP_DUMP_LEVEL is not " - "supported, changing to FULL error" - " prints"); - dpaa2_sec_dp_dump = DPAA2_SEC_DP_FULL_DUMP; - } - } else - return -1; - - return 0; -} - -static void -dpaa2_sec_get_devargs(struct rte_cryptodev *cryptodev, const char *key) -{ - struct rte_kvargs *kvlist; - struct rte_devargs *devargs; - - devargs = cryptodev->device->devargs; - if (!devargs) - return; - - kvlist = rte_kvargs_parse(devargs->args, NULL); - if (!kvlist) - return; - - if (!rte_kvargs_count(kvlist, key)) { - rte_kvargs_free(kvlist); - return; - } - - rte_kvargs_process(kvlist, key, - check_devargs_handler, (void *)cryptodev); - rte_kvargs_free(kvlist); -} - static int dpaa2_sec_dev_init(struct rte_cryptodev *cryptodev) { @@ -4412,6 +4382,9 @@ dpaa2_sec_dev_init(struct rte_cryptodev *cryptodev) internals = cryptodev->data->dev_private; + internals->dump_level = DPAA2_SEC_DP_ERR_DUMP; + dpaax_get_devargs(s_dpaa2_sec_devargs, cryptodev, NULL); + /* * For secondary processes, we don't initialise any further as primary * has already done this work. Only check we don't need a different @@ -4462,8 +4435,6 @@ dpaa2_sec_dev_init(struct rte_cryptodev *cryptodev) internals->token = token; internals->en_loose_ordered = true; - dpaa2_sec_get_devargs(cryptodev, DRIVER_DUMP_MODE); - dpaa2_sec_get_devargs(cryptodev, DRIVER_STRICT_ORDER); DPAA2_SEC_INFO("driver %s: created", cryptodev->data->name); return 0; @@ -4547,6 +4518,6 @@ RTE_PMD_REGISTER_DPAA2(CRYPTODEV_NAME_DPAA2_SEC_PMD, rte_dpaa2_sec_driver); RTE_PMD_REGISTER_CRYPTO_DRIVER(dpaa2_sec_crypto_drv, rte_dpaa2_sec_driver.driver, cryptodev_driver_id); RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_DPAA2_SEC_PMD, - DRIVER_STRICT_ORDER "=<int>" - DRIVER_DUMP_MODE "=<int>"); + DPAA2_DEVARGS(DPAAX_DEVARG_STRING_ENTRY) +); RTE_LOG_REGISTER(dpaa2_logtype_sec, pmd.crypto.dpaa2, NOTICE); diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index 755c8e9cc3..f29817f456 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2020-2024 NXP + * Copyright 2016,2020-2026 NXP * */ @@ -21,6 +21,13 @@ extern uint8_t cryptodev_driver_id; #define FLE_POOL_CACHE_SIZE 512 #define FLE_SG_MEM_SIZE(num) (FLE_POOL_BUF_SIZE + ((num) * 32)) +/* DPAA2_SEC_DP_DUMP levels */ +enum dpaa2_sec_dump_levels { + DPAA2_SEC_DP_NO_DUMP, + DPAA2_SEC_DP_ERR_DUMP, + DPAA2_SEC_DP_FULL_DUMP +}; + #define MAX_QUEUES 64 #define MAX_DESC_SIZE 64 /** private data structure for each DPAA2_SEC device */ @@ -34,6 +41,7 @@ struct dpaa2_sec_dev_private { /**< Max number of queue pairs supported by device */ uint8_t en_ordered; uint8_t en_loose_ordered; + enum dpaa2_sec_dump_levels dump_level; }; struct dpaa2_sec_qp { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 04/65] dma/dpaa2: use table-driven devargs parsing 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (2 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 03/65] crypto/dpaa2_sec: use table-driven devargs parsing Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 05/65] net/dpaa2: unify debug dump via log based helpers Prashant Gupta ` (60 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Convert the dpaa2 qdma devargs handling to the shared dpaax_devargs table so each argument key is declared once and drives both the parse table and the registered valid-args string. Remove the custom check_devargs_handler()/dpaa2_qdma_get_devargs() helpers and parse the arguments once at device init via dpaax_get_devargs(), storing the results in a single dpdmai_dev->flags bitfield (DPAA2_QDMA_FLE_PRE_POPULATE_FLAG, DPAA2_QDMA_DESC_DEBUG_FLAG, DPAA2_QDMA_SHORT_FD_FLAG). This drops the per-virtual-queue fle_pre_populate, using_short_fd and flags fields, which only mirrored device-wide devargs, and makes the copy paths read the device flags directly. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/dma/dpaa2/dpaa2_qdma.c | 92 +++++++++------------------------- drivers/dma/dpaa2/dpaa2_qdma.h | 15 +++--- 2 files changed, 33 insertions(+), 74 deletions(-) diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c index 8d10edfd04..e981bf3e6d 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.c +++ b/drivers/dma/dpaa2/dpaa2_qdma.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2024 NXP + * Copyright 2018-2026 NXP */ #include <rte_eal.h> @@ -11,56 +11,25 @@ #include <mc/fsl_dpdmai.h> #include <rte_pmd_dpaax_qdma.h> +#include <dpaax_devarg.h> #include "dpaa2_hw_dpio.h" #include "dpaa2_qdma.h" #include "dpaa2_qdma_logs.h" -#define DPAA2_QDMA_FLE_PRE_POPULATE "fle_pre_populate" -#define DPAA2_QDMA_DESC_DEBUG "desc_debug" -#define DPAA2_QDMA_USING_SHORT_FD "short_fd" +#define DPAA2_DEVARGS(ENTRY) \ + ENTRY("fle_pre_populate", NULL, DPAA2_QDMA_FLE_PRE_POPULATE_FLAG) \ + ENTRY("desc_debug", NULL, DPAA2_QDMA_DESC_DEBUG_FLAG) \ + ENTRY("short_fd", NULL, DPAA2_QDMA_SHORT_FD_FLAG) + +static const struct dpaax_devargs s_dpaa2_qdma_devargs[] = { + DPAA2_DEVARGS(DPAAX_DEVARG_TABLE_ENTRY) +}; static uint32_t dpaa2_coherent_no_alloc_cache; static uint32_t dpaa2_coherent_alloc_cache; static struct fsl_mc_io s_proc_mc_reg; -static int -check_devargs_handler(__rte_unused const char *key, const char *value, - __rte_unused void *opaque) -{ - if (strcmp(value, "1")) - return -1; - - return 0; -} - -static int -dpaa2_qdma_get_devargs(struct rte_devargs *devargs, const char *key) -{ - struct rte_kvargs *kvlist; - - if (!devargs) - return 0; - - kvlist = rte_kvargs_parse(devargs->args, NULL); - if (!kvlist) - return 0; - - if (!rte_kvargs_count(kvlist, key)) { - rte_kvargs_free(kvlist); - return 0; - } - - if (rte_kvargs_process(kvlist, key, - check_devargs_handler, NULL) < 0) { - rte_kvargs_free(kvlist); - return 0; - } - rte_kvargs_free(kvlist); - - return 1; -} - static inline int qdma_cntx_idx_ring_eq(struct qdma_cntx_idx_ring *ring, const uint16_t *elem, uint16_t nb, @@ -670,7 +639,7 @@ dpaa2_qdma_copy_sg(void *dev_private, DPAA2_SET_FD_COMPOUND_FMT(fd); DPAA2_SET_FD_FLC(fd, (uint64_t)cntx_sg); - if (qdma_vq->fle_pre_populate) { + if (dpdmai_dev->flags & DPAA2_QDMA_FLE_PRE_POPULATE_FLAG) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { fle_sdd_sg_pre_populate(cntx_sg, qdma_vq); if (!qdma_dev->is_silent && cntx_sg && idx_addr) { @@ -698,7 +667,7 @@ dpaa2_qdma_copy_sg(void *dev_private, QBMAN_FLE_WORD4_FMT_SGE); } - if (unlikely(qdma_vq->flags & DPAA2_QDMA_DESC_DEBUG_FLAG)) + if (unlikely(dpdmai_dev->flags & DPAA2_QDMA_DESC_DEBUG_FLAG)) dpaa2_qdma_long_fmt_dump(cntx_sg->fle_sdd.fle); dpaa2_qdma_fd_save_att(fd, 0, DPAA2_QDMA_FD_SG); @@ -844,7 +813,7 @@ dpaa2_qdma_short_copy(struct qdma_virt_queue *qdma_vq, static int dpaa2_qdma_long_copy(struct qdma_virt_queue *qdma_vq, rte_iova_t src, rte_iova_t dst, uint32_t length, - int is_silent, uint64_t flags) + int is_silent, uint64_t flags, uint32_t dev_flags) { int ret = 0, expected; struct qbman_fd *fd = &qdma_vq->fd[qdma_vq->fd_idx]; @@ -872,7 +841,7 @@ dpaa2_qdma_long_copy(struct qdma_virt_queue *qdma_vq, DPAA2_SET_FD_COMPOUND_FMT(fd); DPAA2_SET_FD_FLC(fd, (uint64_t)fle); - if (qdma_vq->fle_pre_populate) { + if (dev_flags & DPAA2_QDMA_FLE_PRE_POPULATE_FLAG) { if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) { fle_sdd_pre_populate(fle_sdd, &qdma_vq->rbp, @@ -888,7 +857,7 @@ dpaa2_qdma_long_copy(struct qdma_virt_queue *qdma_vq, QBMAN_FLE_WORD4_FMT_SBF); } - if (unlikely(qdma_vq->flags & DPAA2_QDMA_DESC_DEBUG_FLAG)) + if (unlikely(dev_flags & DPAA2_QDMA_DESC_DEBUG_FLAG)) dpaa2_qdma_long_fmt_dump(fle); dpaa2_qdma_fd_save_att(fd, DPAA2_QDMA_IDX_FROM_FLAG(flags), @@ -921,12 +890,14 @@ dpaa2_qdma_copy(void *dev_private, uint16_t vchan, struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev; struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan]; - if (qdma_vq->using_short_fd) + if (dpdmai_dev->flags & DPAA2_QDMA_SHORT_FD_FLAG) { return dpaa2_qdma_short_copy(qdma_vq, src, dst, length, qdma_dev->is_silent, flags); - else + } else { return dpaa2_qdma_long_copy(qdma_vq, src, dst, - length, qdma_dev->is_silent, flags); + length, qdma_dev->is_silent, flags, + dpdmai_dev->flags); + } } static inline int @@ -1379,21 +1350,6 @@ dpaa2_qdma_vchan_setup(struct rte_dma_dev *dev, uint16_t vchan, if (ret) return ret; - if (dpaa2_qdma_get_devargs(dev->device->devargs, DPAA2_QDMA_FLE_PRE_POPULATE)) - qdma_dev->vqs[vchan].fle_pre_populate = 1; - else - qdma_dev->vqs[vchan].fle_pre_populate = 0; - - if (dpaa2_qdma_get_devargs(dev->device->devargs, DPAA2_QDMA_DESC_DEBUG)) - qdma_dev->vqs[vchan].flags |= DPAA2_QDMA_DESC_DEBUG_FLAG; - else - qdma_dev->vqs[vchan].flags &= (~DPAA2_QDMA_DESC_DEBUG_FLAG); - - if (dpaa2_qdma_get_devargs(dev->device->devargs, DPAA2_QDMA_USING_SHORT_FD)) - qdma_dev->vqs[vchan].using_short_fd = 1; - else - qdma_dev->vqs[vchan].using_short_fd = 0; - snprintf(pool_name, sizeof(pool_name), "qdma_fle_pool_dev%d_qid%d", dpdmai_dev->dpdmai_id, vchan); pool_size = sizeof(struct qdma_cntx_sg); @@ -1656,6 +1612,9 @@ dpaa2_dpdmai_dev_init(struct rte_dma_dev *dev, uint32_t dpdmai_id) DPAA2_QDMA_FUNC_TRACE(); + dpdmai_dev->flags = 0; + dpaax_get_devargs(s_dpaa2_qdma_devargs, dev, &dpdmai_dev->flags); + if (!dpaa2_coherent_no_alloc_cache) { if (dpaa2_svr_family == SVR_LX2160A) { dpaa2_coherent_no_alloc_cache = @@ -1801,7 +1760,6 @@ static struct rte_dpaa2_driver rte_dpaa2_qdma_pmd = { RTE_PMD_REGISTER_DPAA2(dpaa2_qdma, rte_dpaa2_qdma_pmd); RTE_PMD_REGISTER_PARAM_STRING(dpaa2_qdma, - DPAA2_QDMA_FLE_PRE_POPULATE "=<int>" - DPAA2_QDMA_DESC_DEBUG"=<int>" - DPAA2_QDMA_USING_SHORT_FD"=<int>"); + DPAA2_DEVARGS(DPAAX_DEVARG_STRING_ENTRY) +); RTE_LOG_REGISTER_DEFAULT(dpaa2_qdma_logtype, INFO); diff --git a/drivers/dma/dpaa2/dpaa2_qdma.h b/drivers/dma/dpaa2/dpaa2_qdma.h index e2d2eb4fa8..4a5d1056f0 100644 --- a/drivers/dma/dpaa2/dpaa2_qdma.h +++ b/drivers/dma/dpaa2/dpaa2_qdma.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2024 NXP + * Copyright 2018-2026 NXP */ #ifndef _DPAA2_QDMA_H_ @@ -233,6 +233,12 @@ struct __rte_packed_begin qdma_cntx_sg { #define DPAA2_QDMA_IDX_FROM_FLAG(flag) \ ((flag) >> RTE_DPAAX_QDMA_COPY_IDX_OFFSET) +enum dpaa2_dpdmai_dev_flags { + DPAA2_QDMA_FLE_PRE_POPULATE_FLAG = RTE_BIT32(0), + DPAA2_QDMA_DESC_DEBUG_FLAG = RTE_BIT32(1), + DPAA2_QDMA_SHORT_FD_FLAG = RTE_BIT32(2) +}; + /** Represents a DPDMAI device */ struct dpaa2_dpdmai_dev { /** Pointer to Next device instance */ @@ -247,6 +253,7 @@ struct dpaa2_dpdmai_dev { struct dpaa2_queue rx_queue[DPAA2_DPDMAI_MAX_QUEUES]; /** TX queues */ struct dpaa2_queue tx_queue[DPAA2_DPDMAI_MAX_QUEUES]; + uint32_t flags; struct qdma_device *qdma_dev; }; @@ -261,8 +268,6 @@ struct qdma_cntx_idx_ring { uint16_t nb_in_ring; }; -#define DPAA2_QDMA_DESC_DEBUG_FLAG (1 << 0) - /** Represents a QDMA virtual queue */ struct qdma_virt_queue { /** Associated hw queue */ @@ -273,8 +278,6 @@ struct qdma_virt_queue { void **fle_elem; /** Route by port */ struct dpaa2_qdma_rbp rbp; - /** States if this vq is in use or not */ - uint8_t fle_pre_populate; /** Number of descriptor for the virtual DMA channel */ uint16_t nb_desc; /* Total number of enqueues on this VQ */ @@ -284,7 +287,6 @@ struct qdma_virt_queue { uint64_t copy_num; uint16_t vq_id; - uint32_t flags; struct qbman_fd fd[DPAA2_QDMA_MAX_DESC]; uint16_t fd_idx; struct qdma_cntx_idx_ring *ring_cntx_idx; @@ -295,7 +297,6 @@ struct qdma_virt_queue { uint16_t silent_idx; int num_valid_jobs; - int using_short_fd; struct rte_dma_stats stats; }; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 05/65] net/dpaa2: unify debug dump via log based helpers 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (3 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 04/65] dma/dpaa2: " Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 06/65] net/dpaa2: expose Rx L3/L4/L5 offsets via mbuf dynfield Prashant Gupta ` (59 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The dpaa2 PMD printed debug output through several unrelated paths: the flow dump used a raw printf, and the Rx error queue dump used rte_hexdump() straight to stderr with sprintf-built titles. None of these went through the DPDK logging framework, so they could not be filtered and bypassed any configured log stream. Route all debug dumps through the dpaa2 dump helpers instead. Point DPAA2_FLOW_DUMP at dpaa2_dump_print(), and add a dpaa2_dump_hex_print() helper that emits a buffer as hex using the same path. Convert the Rx error packet dump to use these helpers, rename dump_err_pkts() to dpaa2_dev_rx_err_pkts_dump() for consistency with the other datapath helpers, use rte_pktmbuf_mtod() for the segment payload, and simplify the surrounding code. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 4 +-- drivers/net/dpaa2/dpaa2_pmd_logs.h | 17 ++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 51 +++++++++++++----------------- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 979ab4cae0..d9ca7211c7 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2022 NXP + * Copyright 2018-2026 NXP */ #include <sys/queue.h> @@ -196,7 +196,7 @@ static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { #endif -#define DPAA2_FLOW_DUMP printf +#define DPAA2_FLOW_DUMP dpaa2_dump_print static inline void dpaa2_prot_field_string(uint32_t prot, uint32_t field, diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 8b699bb5af..51fdabf94b 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -51,4 +51,21 @@ dpaa2_dump_print(const char *fmt, ...) rte_vlog(RTE_LOG_NOTICE, RTE_LOGTYPE_USER1, fmt, ap); va_end(ap); } + +#define DPAA2_DUMP_HEX_LINE_SIZE 32 + +static inline void +dpaa2_dump_hex_print(const uint8_t *buf, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + dpaa2_dump_print("%02x ", buf[i]); + + if (!((i + 1) % DPAA2_DUMP_HEX_LINE_SIZE)) + dpaa2_dump_print("\n"); + } + if (len % DPAA2_DUMP_HEX_LINE_SIZE) + dpaa2_dump_print("\n"); +} #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index d3512d56f9..060f525233 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -675,13 +675,14 @@ return 0; } static void -dump_err_pkts(struct dpaa2_queue *dpaa2_q) +dpaa2_dev_rx_err_pkts_dump(struct dpaa2_queue *dpaa2_q) { /* Function receive frames for a given device and VQ */ struct qbman_result *dq_storage; uint32_t fqid = dpaa2_q->fqid; - int ret, num_rx = 0; + int ret, num_rx = 0, i; uint8_t pending, status; + const uint8_t *buf; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; @@ -689,15 +690,13 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) uint32_t lcore_id = rte_lcore_id(); void *v_addr, *hw_annot_addr; struct dpaa2_fas *fas; - struct rte_mbuf *mbuf; - char title[32]; + struct rte_mbuf *mbuf, *seg; struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", - rte_gettid()); + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return; } } @@ -738,8 +737,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) pending = 0; /* Check for valid frame. */ status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & - QBMAN_DQ_STAT_VALIDFRAME) == 0)) + if (unlikely(!(status & QBMAN_DQ_STAT_VALIDFRAME))) continue; } fd = qbman_result_DQ_fd(dq_storage); @@ -759,27 +757,22 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd), fas->status); - if (mbuf) { - __rte_mbuf_sanity_check(mbuf, 1); - if (mbuf->nb_segs > 1) { - struct rte_mbuf *seg = mbuf; - int i = 0; - - while (seg) { - sprintf(title, "Payload seg[%d]", i); - rte_hexdump(stderr, title, - (char *)seg->buf_addr + seg->data_off, - seg->data_len); - seg = seg->next; - i++; - } - } else { - rte_hexdump(stderr, "Payload", - (char *)mbuf->buf_addr + mbuf->data_off, - mbuf->data_len); + __rte_mbuf_sanity_check(mbuf, 1); + if (mbuf->nb_segs > 1) { + seg = mbuf; + i = 0; + while (seg) { + buf = rte_pktmbuf_mtod(seg, const uint8_t *); + dpaa2_dump_print("Payload seg[%d]\n", i); + dpaa2_dump_hex_print(buf, seg->data_len); + seg = seg->next; + i++; } - rte_pktmbuf_free(mbuf); + } else { + buf = rte_pktmbuf_mtod(mbuf, const uint8_t *); + dpaa2_dump_hex_print(buf, mbuf->data_len); } + rte_pktmbuf_free(mbuf); dq_storage++; num_rx++; } while (pending); @@ -812,7 +805,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); + dpaa2_dev_rx_err_pkts_dump(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -1080,7 +1073,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct dpaa2_dev_priv *priv = eth_data->dev_private; if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); + dpaa2_dev_rx_err_pkts_dump(priv->rx_err_vq); if (by_channel) { if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 06/65] net/dpaa2: expose Rx L3/L4/L5 offsets via mbuf dynfield 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (4 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 05/65] net/dpaa2: unify debug dump via log based helpers Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 07/65] net/dpaa2: optimize dpaa2 Tx queue and channel mapping Prashant Gupta ` (58 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 WRIOP parser already writes the L3, L4 and L5 header offsets of each received frame into the hardware annotation area (FAS word6). Applications that want to work with inner headers (IPsec, tunnel decap, L5 inspection, etc.) currently have to re-parse the packet in software even though the information is a single load away. Expose it through a per-mbuf dynfield so the PMD can hand it to the application without touching generic mbuf fields. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 29 +++++++++- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++ drivers/net/dpaa2/dpaa2_rxtx.c | 89 +++++++++++++++++++++++++++++++ drivers/net/dpaa2/rte_pmd_dpaa2.h | 4 ++ 4 files changed, 133 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index cd39c7874e..9a0dacfe4e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -33,6 +33,32 @@ #include <fsl_qbman_debug.h> #include <dpaax_devarg.h> +static const struct rte_mbuf_dynfield s_dpaa2_rx_protocol_pos_dyn = { + .name = "dpaa2_rx_protocol_pos_dyn", + .size = sizeof(struct dpaa2_dyn_rx_protocol_pos), + .align = __alignof__(struct dpaa2_dyn_rx_protocol_pos), +}; + +static void +dpaa2_dev_args_parser_offset_en(void *vdev, + const struct rte_kvargs_pair *pair) +{ + struct rte_eth_dev *dev = vdev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret, val = atoi(pair->value); + + if (!val) + return; + + ret = rte_mbuf_dynfield_register(&s_dpaa2_rx_protocol_pos_dyn); + if (ret < 0) { + DPAA2_PMD_ERR("Failed(%d) to register for protocol pos", ret); + return; + } + DPAA2_PMD_INFO("Register mbuf offset(%d) for protocol pos", ret); + priv->psr_dynfield_offset = ret | DPAA2_PSR_DYNFIELD_OFFSET_EN; +} + /* Single source of truth for dpaa2 devargs: * ENTRY(key-string, handle, flag-bit) * handle is an optional per-arg callback (NULL if the arg only sets a flag). @@ -48,7 +74,8 @@ ENTRY("drv_rx_print_parser_result", NULL, DPAA2_RX_PRINT_PSR_RESULT_FLAG) \ ENTRY("drv_err_queue", NULL, DPAA2_RX_ERROR_QUEUE_FLAG) \ ENTRY("drv_no_taildrop", NULL, DPAA2_RX_TAILDROP_OFF) \ - ENTRY("drv_no_data_stashing", NULL, DPAA2_RX_DATA_STASHING_OFF_FLAG) + ENTRY("drv_no_data_stashing", NULL, DPAA2_RX_DATA_STASHING_OFF_FLAG) \ + ENTRY("drv_parse_protocol_offset", dpaa2_dev_args_parser_offset_en, 0) #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_REPEAT_TIME 90 /* 9s (90 * 100ms) in total */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 5b51414000..98430e3f66 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -58,6 +58,10 @@ #define CONG_RETRY_COUNT 18000 +#define DPAA2_PSR_DYNFIELD_OFFSET_EN RTE_BIT32(31) +#define DPAA2_PSR_DYNFIELD_OFFSET_MASK \ + (DPAA2_PSR_DYNFIELD_OFFSET_EN - 1) + /* RX queue tail drop threshold * currently considering 64 KB packets */ @@ -234,6 +238,13 @@ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + #define DPAA2_FS_FLC_FS_MARK_OFFSET \ (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) @@ -436,6 +447,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + uint32_t psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 060f525233..02494686d3 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -46,6 +46,83 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); } +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} + +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) +{ + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + pos = RTE_MBUF_DYNFIELD(mbuf, + priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_MASK, + struct dpaa2_dyn_rx_protocol_pos *); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_rx_get_offset, 26.11) +int +rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, + uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off) +{ + struct rte_eth_dev *dev; + struct dpaa2_dyn_rx_protocol_pos *pos; + struct dpaa2_dev_priv *priv; + + if (port_id >= RTE_MAX_ETHPORTS) + port_id = m->port; + + if (unlikely(!rte_pmd_dpaa2_dev_is_dpaa2(port_id))) + return -EINVAL; + + dev = &rte_eth_devices[port_id]; + if (!dev->data) + return -EINVAL; + + if (!dev->data->dev_private) + return -EINVAL; + + priv = dev->data->dev_private; + if (unlikely(!(priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN))) { + DPAA2_PMD_ERR("Not register for RX protocol pos."); + + return -EINVAL; + } + pos = RTE_MBUF_DYNFIELD(m, + priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_MASK, + struct dpaa2_dyn_rx_protocol_pos *); + + if (l3_off) + *l3_off = pos->l3_offset; + if (l4_off) + *l4_off = pos->l4_offset; + if (l5_off) + *l5_off = pos->l5_offset; + + return 0; +} + #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ DPAA2_SET_FD_ADDR(_fd, DPAA2_MBUF_VADDR_TO_IOVA(_mbuf)); \ DPAA2_SET_FD_LEN(_fd, _mbuf->data_len); \ @@ -745,10 +822,14 @@ dpaa2_dev_rx_err_pkts_dump(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); @@ -912,10 +993,14 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, fd = qbman_result_DQ_fd(dq_storage); + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); @@ -1158,10 +1243,14 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, fd = qbman_result_DQ_fd(dq_storage); + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index 83bee098bc..128adf3d1d 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -144,6 +144,10 @@ rte_pmd_dpaa2_dev_is_dpaa2(uint32_t eth_id); __rte_experimental const char * rte_pmd_dpaa2_ep_name(uint32_t eth_id); +__rte_experimental +int +rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, + uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off); #if defined(RTE_LIBRTE_IEEE1588) __rte_experimental -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 07/65] net/dpaa2: optimize dpaa2 Tx queue and channel mapping 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (5 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 06/65] net/dpaa2: expose Rx L3/L4/L5 offsets via mbuf dynfield Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 08/65] bus/fslmc: split bus-level device walk from VFIO primitives Prashant Gupta ` (57 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Allocate TX queues based on dpni attribute and align the bounds check with the RX queue logic: - compute nb_tx_queues from num_tx_tcs * num_queues (respecting DPNI_OPT_SINGLE_SENDER) and cap at MAX_TX_QUEUES (128) - cap nb_rx_queues at MAX_RX_QUEUES (128) - cap num_channels at DPAA2_MAX_CHANNELS - assign tc_index/flow_id at queue-allocation time instead of at queue-setup time - replace the open-coded (channel << 8 | tc) with DPNI_BUILD_PARAM(channel, tc) throughout tx_queue_setup - initialize fqid to DPAA2_INVALID_FQ_ID and use it as the already-configured guard (replacing DPAA2_INVALID_FLOW_ID) - add a per-device tx_channels[] array for channel mapping Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/dpaa2_ethdev.c | 119 +++++++++++++++--------- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +- 3 files changed, 78 insertions(+), 47 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 556e1b01c0..52f4434928 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -83,6 +83,7 @@ #define DPAA2_DPCI_MAX_QUEUES 2 #define DPAA2_INVALID_FLOW_ID 0xffff +#define DPAA2_INVALID_FQ_ID ((uint32_t)(-1)) #define DPAA2_INVALID_CGID 0xff #define SEC_FLC_DHR_OUTBOUND (-114) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 9a0dacfe4e..f697454d1a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -558,17 +558,13 @@ static int dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint16_t dist_idx; - uint32_t vq_id; - uint8_t num_rxqueue_per_tc; - struct dpaa2_queue *mc_q, *mcq; + uint8_t num_queue_per_tc; + struct dpaa2_queue *mc_q, *dpaa2_q; uint32_t tot_queues; int i, ret = 0; - struct dpaa2_queue *dpaa2_q; PMD_INIT_FUNC_TRACE(); - num_rxqueue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); if (priv->flags & DPAA2_TX_CONF_ENABLE) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else @@ -580,8 +576,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) return -ENOBUFS; } + num_queue_per_tc = (priv->nb_rx_queues / priv->num_rx_tc); for (i = 0; i < priv->nb_rx_queues; i++) { mc_q->eth_data = dev->data; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->rx_vq[i] = mc_q++; dpaa2_q = priv->rx_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -605,9 +605,12 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } + num_queue_per_tc = (priv->nb_tx_queues / priv->num_tx_tc); for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->flow_id = DPAA2_INVALID_FLOW_ID; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_vq[i] = mc_q++; dpaa2_q = (struct dpaa2_queue *)priv->tx_vq[i]; dpaa2_q->cscn = rte_malloc(NULL, @@ -622,8 +625,9 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; - mc_q->tc_index = i; - mc_q->flow_id = 0; + mc_q->tc_index = i / num_queue_per_tc; + mc_q->flow_id = i % num_queue_per_tc; + mc_q->fqid = DPAA2_INVALID_FQ_ID; priv->tx_conf_vq[i] = mc_q++; dpaa2_q = priv->tx_conf_vq[i]; ret = dpaa2_queue_storage_alloc(dpaa2_q, @@ -633,14 +637,6 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - vq_id = 0; - for (dist_idx = 0; dist_idx < priv->nb_rx_queues; dist_idx++) { - mcq = priv->rx_vq[vq_id]; - mcq->tc_index = dist_idx / num_rxqueue_per_tc; - mcq->flow_id = dist_idx % num_rxqueue_per_tc; - vq_id++; - } - return 0; fail_tx_conf: i -= 1; @@ -1016,6 +1012,12 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, return ret; } dpaa2_q = priv->rx_vq[rx_queue_id]; + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: RXQ[%d] has been setup", + dev->data->name, rx_queue_id); + dev->data->rx_queues[rx_queue_id] = dpaa2_q; + return 0; + } dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1204,7 +1206,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->offloads = tx_conf->offloads; /* Return if queue already configured */ - if (dpaa2_q->flow_id != DPAA2_INVALID_FLOW_ID) { + if (dpaa2_q->fqid != DPAA2_INVALID_FQ_ID) { + DPAA2_PMD_WARN("%s: TXQ[%d] has been setup", + dev->data->name, tx_queue_id); dev->data->tx_queues[tx_queue_id] = dpaa2_q; return 0; } @@ -1212,26 +1216,24 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - tc_id = tx_queue_id % priv->num_tx_tc; - channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; - flow_id = 0; + tc_id = dpaa2_q->tc_index; + flow_id = dpaa2_q->flow_id; + if (tc_id < priv->num_channels) + channel_id = priv->tx_channels[tc_id]; + else + channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); if (ret) { - DPAA2_PMD_ERR("Error in setting the tx flow: " - "tc_id=%d, flow=%d err=%d", - tc_id, flow_id, ret); - return ret; + DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", + ret, dev->data->name, tc_id, flow_id); + return ret; } - dpaa2_q->flow_id = flow_id; - - dpaa2_q->tc_index = tc_id; - ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, ((channel_id << 8) | dpaa2_q->tc_index), - dpaa2_q->flow_id, &tx_flow_cfg, &qid); + DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1270,10 +1272,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_set_congestion_notification(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - ((channel_id << 8) | tc_id), &cong_notif_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), &cong_notif_cfg); if (ret) { - DPAA2_PMD_ERR("Set TX congestion notification err=%d", - ret); + DPAA2_PMD_ERR("Set TX congestion notification err=%d", ret); return ret; } } @@ -1281,31 +1282,32 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dev->data->tx_queues[tx_queue_id] = dpaa2_q; if (priv->flags & DPAA2_TX_CONF_ENABLE) { + tc_id = dpaa2_tx_conf_q->tc_index; + flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; options = options | DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, - options, &tx_conf_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, options, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", - dpaa2_tx_conf_q->tc_index, - dpaa2_tx_conf_q->flow_id, ret); + tc_id, flow_id, ret); return ret; } ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, - ((channel_id << 8) | dpaa2_tx_conf_q->tc_index), - dpaa2_tx_conf_q->flow_id, &tx_conf_cfg, &qid); + DPNI_BUILD_PARAM(channel_id, tc_id), + flow_id, &tx_conf_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; } dpaa2_tx_conf_q->fqid = qid.fqid; } + return 0; } @@ -1364,6 +1366,8 @@ dpaa2_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id) /* keep the DPCON on the FQ across a reconfigure; freed at dev_close */ if (dpaa2_q->napi_dpcon) dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); + + dpaa2_q->fqid = DPAA2_INVALID_FQ_ID; } static int @@ -3448,6 +3452,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; struct dpni_buffer_layout layout; int ret, hw_id, i; + uint16_t num_q_per_tc, max_q_per_tc; PMD_INIT_FUNC_TRACE(); @@ -3534,10 +3539,34 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; - for (i = 0; i < attr.num_rx_tcs; i++) - priv->nb_rx_queues += attr.num_queues; + num_q_per_tc = attr.num_queues; + max_q_per_tc = MAX_RX_QUEUES / attr.num_rx_tcs; + + if (num_q_per_tc > max_q_per_tc) { + DPAA2_PMD_WARN("Too many RXQs per TC(%u) > %u, reduce it to %u", + num_q_per_tc, max_q_per_tc, max_q_per_tc); + num_q_per_tc = max_q_per_tc; + } + priv->nb_rx_queues = attr.num_rx_tcs * num_q_per_tc; - priv->nb_tx_queues = attr.num_tx_tcs * attr.num_channels; + max_q_per_tc = MAX_TX_QUEUES / attr.num_tx_tcs; + if (attr.options & DPNI_OPT_SINGLE_SENDER) + num_q_per_tc = 1; + else + num_q_per_tc = attr.num_queues; + if (num_q_per_tc > max_q_per_tc) { + DPAA2_PMD_WARN("Too many TXQs per TC(%u) > %u, reduce it to %u", + num_q_per_tc, max_q_per_tc, max_q_per_tc); + num_q_per_tc = max_q_per_tc; + } + priv->nb_tx_queues = attr.num_tx_tcs * num_q_per_tc; + if (priv->num_channels > DPAA2_MAX_CHANNELS) { + DPAA2_PMD_WARN("Too many TX channels(%d) > %d, reduce it to %d", + priv->num_channels, DPAA2_MAX_CHANNELS, DPAA2_MAX_CHANNELS); + priv->num_channels = DPAA2_MAX_CHANNELS; + } + for (i = 0; i < priv->num_channels; i++) + priv->tx_channels[i] = i; DPAA2_PMD_DEBUG("RX-TC= %d, rx_queues= %d, tx_queues=%d, max_cgs=%d", priv->num_rx_tc, priv->nb_rx_queues, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 98430e3f66..16e55412db 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -30,7 +30,7 @@ #define MAX_TCS DPNI_MAX_TC #define MAX_RX_QUEUES 128 -#define MAX_TX_QUEUES 16 +#define MAX_TX_QUEUES 128 #define MAX_DPNI 8 #define DPAA2_MAX_CHANNELS 16 @@ -438,13 +438,14 @@ struct dpaa2_dev_priv { int32_t hw_id; int32_t qdid; uint16_t token; + uint16_t tx_channels[DPAA2_MAX_CHANNELS]; uint8_t nb_tx_queues; uint8_t nb_rx_queues; uint32_t options; void *rx_vq[MAX_RX_QUEUES]; void *tx_vq[MAX_TX_QUEUES]; struct dpaa2_bp_list *bp_list; /**<Attached buffer pool list */ - void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; + void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ uint32_t psr_dynfield_offset; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 08/65] bus/fslmc: split bus-level device walk from VFIO primitives 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (6 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 07/65] net/dpaa2: optimize dpaa2 Tx queue and channel mapping Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 15:00 ` David Marchand 2026-10-23 13:42 ` [PATCH v4-S3 09/65] bus/fslmc: centralize MC version and SoC detection in the bus layer Prashant Gupta ` (56 subsequent siblings) 64 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The fslmc bus and its VFIO backend were tangled: VFIO-internal types and DPAA2_MC_*_DEVID constants were exposed in a public header, and the device-iteration / blocklist / primary-secondary policy for probe and close lived inside fslmc_vfio.c (fslmc_vfio_process_group / fslmc_vfio_close_group) even though it is pure bus logic. On top of that, several bus-internal symbols were still declared with public "fslmc_*" names. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/fslmc_bus.c | 217 ++++++++++++- drivers/bus/fslmc/fslmc_vfio.c | 391 ++++++----------------- drivers/bus/fslmc/fslmc_vfio.h | 48 +-- drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 3 +- drivers/bus/fslmc/private.h | 14 +- 5 files changed, 326 insertions(+), 347 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index 1c638a2d82..7116817c75 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2018-2021 NXP + * Copyright 2016,2018-2021, 2026 NXP * */ @@ -332,7 +332,7 @@ rte_fslmc_scan(void) goto scan_fail; } - ret = fslmc_get_container_group(group_name, &groupid); + ret = fslmc_vfio_get_container_group(group_name, &groupid); if (ret != 0) goto scan_fail; @@ -383,6 +383,175 @@ rte_fslmc_scan(void) return 0; } +static int +fslmc_bus_process_iodevices(void) +{ + int ret; + int found_mportal = 0; + struct rte_dpaa2_device *dev; + bool is_dpmcp_in_blocklist = false, is_dpio_in_blocklist = false; + int dpmcp_count = 0, dpio_count = 0, current_device; + + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { + if (dev->dev_type == DPAA2_MPORTAL) { + dpmcp_count++; + if (dev->device.devargs && + dev->device.devargs->policy == RTE_DEV_BLOCKED) + is_dpmcp_in_blocklist = true; + } + if (dev->dev_type == DPAA2_IO) { + dpio_count++; + if (dev->device.devargs && + dev->device.devargs->policy == RTE_DEV_BLOCKED) + is_dpio_in_blocklist = true; + } + } + + /* Search the MCP as that should be initialized first. */ + current_device = 0; + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { + if (dev->dev_type == DPAA2_MPORTAL) { + current_device++; + if (dev->device.devargs && + dev->device.devargs->policy == RTE_DEV_BLOCKED) { + DPAA2_BUS_DEBUG("%s Blocked, skipping", dev->device.name); + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + continue; + } + + if (rte_eal_process_type() == RTE_PROC_SECONDARY && + !is_dpmcp_in_blocklist) { + if (dpmcp_count == 1 || + current_device != dpmcp_count) { + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + continue; + } + } + + if (!found_mportal) { + ret = fslmc_vfio_process_mcp(dev); + if (ret) { + DPAA2_BUS_ERR("Unable to map MC Portal"); + return ret; + } + found_mportal = 1; + } + + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + free(dev); + dev = NULL; + /* Ideally there is only a single dpmcp, but in case + * multiple exists, looping on remaining devices. + */ + } + } + + /* Cannot continue if there is not even a single mportal */ + if (!found_mportal) { + DPAA2_BUS_ERR("No MC Portal device found. Not continuing"); + return -EIO; + } + + /* Search for DPRC device next as it updates endpoint of + * other devices. + */ + current_device = 0; + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { + if (dev->dev_type == DPAA2_DPRC) { + ret = fslmc_vfio_process_iodevices(dev); + if (ret) { + DPAA2_BUS_ERR("Unable to process dprc"); + return ret; + } + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + } + } + + current_device = 0; + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { + if (dev->dev_type == DPAA2_IO) + current_device++; + if (dev->device.devargs && + dev->device.devargs->policy == RTE_DEV_BLOCKED) { + DPAA2_BUS_DEBUG("%s Blocked, skipping", dev->device.name); + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + continue; + } + if (rte_eal_process_type() == RTE_PROC_SECONDARY && + dev->dev_type != DPAA2_ETH && + dev->dev_type != DPAA2_CRYPTO && + dev->dev_type != DPAA2_QDMA && + dev->dev_type != DPAA2_IO) { + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + continue; + } + switch (dev->dev_type) { + case DPAA2_ETH: + case DPAA2_CRYPTO: + case DPAA2_QDMA: + ret = fslmc_vfio_process_iodevices(dev); + if (ret) { + DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); + return ret; + } + break; + case DPAA2_CON: + case DPAA2_CI: + case DPAA2_BPOOL: + case DPAA2_DPRTC: + case DPAA2_MUX: + /* IN case of secondary processes, all control objects + * like dpbp, dpcon, dpci are not initialized/required + * - all of these are assumed to be initialized and made + * available by primary. + */ + if (rte_eal_process_type() == RTE_PROC_SECONDARY) + continue; + + /* Call the object creation routine and remove the + * device entry from device list + */ + ret = fslmc_vfio_process_iodevices(dev); + if (ret) { + DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); + return ret; + } + + break; + case DPAA2_IO: + if (!is_dpio_in_blocklist && dpio_count > 1) { + if (rte_eal_process_type() == RTE_PROC_SECONDARY + && current_device != dpio_count) { + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + break; + } + if (rte_eal_process_type() == RTE_PROC_PRIMARY + && current_device == dpio_count) { + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + break; + } + } + + ret = fslmc_vfio_process_iodevices(dev); + if (ret) { + DPAA2_BUS_DEBUG("Dev (%s) init failed", dev->device.name); + return ret; + } + + break; + case DPAA2_UNKNOWN: + default: + /* Unknown - ignore */ + DPAA2_BUS_DEBUG("Found unknown device (%s)", dev->device.name); + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + free(dev); + dev = NULL; + } + } + + return 0; +} + /* Bus initialization needs the DPDK heap and DMA mapping of the memory * segments, which EAL only sets up after the bus scan, so it is done here. */ @@ -424,7 +593,7 @@ rte_fslmc_probe(struct rte_bus *bus) } } - ret = fslmc_vfio_process_group(); + ret = fslmc_bus_process_iodevices(); if (ret) { DPAA2_BUS_ERR("Unable to setup devices %d", ret); return ret; @@ -445,12 +614,52 @@ fslmc_bus_match(const struct rte_driver *drv, const struct rte_device *dev) return false; } +static int +fslmc_bus_close_group(void) +{ + struct rte_dpaa2_device *dev; + + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { + if (dev->device.devargs && + dev->device.devargs->policy == RTE_DEV_BLOCKED) { + DPAA2_BUS_DEBUG("%s Blacklisted, skipping", dev->device.name); + rte_bus_remove_device(&rte_fslmc_bus, &dev->device); + continue; + } + switch (dev->dev_type) { + case DPAA2_ETH: + case DPAA2_CRYPTO: + case DPAA2_QDMA: + case DPAA2_IO: + fslmc_vfio_close_iodevices(dev); + break; + case DPAA2_CON: + case DPAA2_CI: + case DPAA2_BPOOL: + case DPAA2_MUX: + if (rte_eal_process_type() == RTE_PROC_SECONDARY) + continue; + + fslmc_vfio_close_iodevices(dev); + break; + case DPAA2_DPRTC: + default: + DPAA2_BUS_DEBUG("Device cannot be closed: Not supported (%s)", + dev->device.name); + } + } + + fslmc_vfio_clear_group(); + + return 0; +} + static int rte_fslmc_close(struct rte_bus *bus __rte_unused) { int ret = 0; - ret = fslmc_vfio_close_group(); + ret = fslmc_bus_close_group(); if (ret) DPAA2_BUS_INFO("Unable to close devices %d", ret); diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index adde629ce6..5b22e985b1 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2024 NXP + * Copyright 2016-2024, 2026 NXP * */ @@ -47,6 +47,29 @@ #define FSLMC_VFIO_MP "fslmc_vfio_mp_sync" +struct fslmc_vfio_device { + LIST_ENTRY(fslmc_vfio_device) next; + int fd; /* fslmc root container device ?? */ + int index; /*index of child object */ + char dev_name[64]; + struct fslmc_vfio_device *child; /* Child object */ +}; + +struct fslmc_vfio_group { + LIST_ENTRY(fslmc_vfio_group) next; + int fd; /* /dev/vfio/"groupid" */ + int groupid; + int connected; + char group_name[64]; /* dprc.x*/ + int iommu_type; + LIST_HEAD(, fslmc_vfio_device) vfio_devices; +}; + +struct fslmc_vfio_container { + int fd; /* /dev/vfio/vfio */ + LIST_HEAD(, fslmc_vfio_group) groups; +}; + /* Container is composed by multiple groups, however, * now each process only supports single group with in container. */ @@ -202,11 +225,44 @@ fslmc_vfio_add_group(int vfio_group_fd, } static int -fslmc_vfio_clear_group(int vfio_group_fd) +fslmc_vfio_group_fd_by_name(const char *group_name) +{ + struct fslmc_vfio_group *group; + + LIST_FOREACH(group, &s_vfio_container.groups, next) { + if (!strcmp(group->group_name, group_name)) + return group->fd; + } + return -ENODEV; +} + +static int +fslmc_vfio_group_fd(void) +{ + const char *group_name = fslmc_vfio_get_group_name(); + int vfio_group_fd; + + vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name); + if (vfio_group_fd <= 0) { + DPAA2_BUS_INFO("%s: Get fd by name(%s) failed(%d)", + __func__, group_name, vfio_group_fd); + if (vfio_group_fd < 0) + return vfio_group_fd; + return -EIO; + } + + return vfio_group_fd; +} + +void +fslmc_vfio_clear_group(void) { struct fslmc_vfio_group *group; struct fslmc_vfio_device *dev; - int clear = 0; + int clear = 0, vfio_group_fd = fslmc_vfio_group_fd(); + + if (vfio_group_fd < 0) + return; LIST_FOREACH(group, &s_vfio_container.groups, next) { if (group->fd == vfio_group_fd) { @@ -228,10 +284,8 @@ fslmc_vfio_clear_group(int vfio_group_fd) s_vfio_container.fd = -1; } - if (clear) - return 0; - - return -ENODEV; + if (!clear) + DPAA2_BUS_ERR("Failed to find vfio group"); } static int @@ -276,18 +330,6 @@ fslmc_vfio_iommu_type(int vfio_group_fd) return -ENODEV; } -static int -fslmc_vfio_group_fd_by_name(const char *group_name) -{ - struct fslmc_vfio_group *group; - - LIST_FOREACH(group, &s_vfio_container.groups, next) { - if (!strcmp(group->group_name, group_name)) - return group->fd; - } - return -ENODEV; -} - static int fslmc_vfio_group_fd_by_id(int group_id) { @@ -356,7 +398,7 @@ fslmc_vfio_container_fd(void) } static int -fslmc_get_group_id(const char *group_name, +fslmc_vfio_get_group_id(const char *group_name, int *groupid) { int ret; @@ -393,7 +435,7 @@ fslmc_vfio_open_group_fd(const char *group_name) if (vfio_group_fd > 0) return vfio_group_fd; - ret = fslmc_get_group_id(group_name, &iommu_group_num); + ret = fslmc_vfio_get_group_id(group_name, &iommu_group_num); if (ret) return ret; /* if primary, try to open the group */ @@ -568,7 +610,7 @@ fslmc_vfio_open_container_fd(void) } int -fslmc_get_container_group(const char *group_name, +fslmc_vfio_get_container_group(const char *group_name, int *groupid) { int ret; @@ -578,7 +620,7 @@ fslmc_get_container_group(const char *group_name, return -EINVAL; } - ret = fslmc_get_group_id(group_name, groupid); + ret = fslmc_vfio_get_group_id(group_name, groupid); if (ret) return ret; @@ -1246,9 +1288,9 @@ fslmc_vfio_setup_device(const char *dev_addr, dev_addr); } -static intptr_t vfio_map_mcp_obj(const char *mcp_obj) +static void *fslmc_vfio_map_mcp_obj(const char *mcp_obj) { - intptr_t v_addr = (intptr_t)MAP_FAILED; + void *v_addr = MAP_FAILED; int32_t ret, mc_fd; struct vfio_group_status status = { .argsz = sizeof(status) }; @@ -1264,7 +1306,7 @@ static intptr_t vfio_map_mcp_obj(const char *mcp_obj) goto MC_FAILURE; } - v_addr = (size_t)mmap(NULL, reg_info.size, + v_addr = mmap(NULL, reg_info.size, PROT_WRITE | PROT_READ, MAP_SHARED, mc_fd, reg_info.offset); @@ -1386,13 +1428,17 @@ rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, return -EIO; } -static void -fslmc_close_iodevices(struct rte_dpaa2_device *dev, - int vfio_fd) +void +fslmc_vfio_close_iodevices(struct rte_dpaa2_device *dev) { struct rte_dpaa2_object *object = NULL; const struct rte_dpaa2_driver *drv; - int ret; + int ret, vfio_fd = fslmc_vfio_group_fd(); + + if (vfio_fd <= 0) { + DPAA2_BUS_ERR("Failed(%d) to get vfio group fd", vfio_fd); + return; + } switch (dev->dev_type) { case DPAA2_IO: @@ -1430,11 +1476,11 @@ fslmc_close_iodevices(struct rte_dpaa2_device *dev, } /* - * fslmc_process_iodevices for processing only IO (ETH, CRYPTO, and possibly + * fslmc_vfio_process_iodevices for processing only IO (ETH, CRYPTO, and possibly * EVENT) devices. */ -static int -fslmc_process_iodevices(struct rte_dpaa2_device *dev) +int +fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev) { int dev_fd, ret; struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; @@ -1475,13 +1521,11 @@ fslmc_process_iodevices(struct rte_dpaa2_device *dev) return 0; } -static int -fslmc_process_mcp(struct rte_dpaa2_device *dev) +int +fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev) { int ret; - intptr_t v_addr; - struct fsl_mc_io dpmng = {0}; - struct mc_version mc_ver_info = {0}; + void *v_addr; rte_mcp_ptr_list = malloc(sizeof(void *) * (MC_PORTAL_INDEX + 1)); if (!rte_mcp_ptr_list) { @@ -1490,41 +1534,22 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) goto cleanup; } - v_addr = vfio_map_mcp_obj(dev->device.name); - if (v_addr == (intptr_t)MAP_FAILED) { + v_addr = fslmc_vfio_map_mcp_obj(dev->device.name); + if (v_addr == MAP_FAILED) { DPAA2_BUS_ERR("Error mapping region (errno = %d)", errno); ret = -1; goto cleanup; } - /* check the MC version compatibility */ - dpmng.regs = (void *)v_addr; - /* In case of secondary processes, MC version check is no longer * required. */ if (rte_eal_process_type() == RTE_PROC_SECONDARY) { - rte_mcp_ptr_list[MC_PORTAL_INDEX] = (void *)v_addr; + rte_mcp_ptr_list[MC_PORTAL_INDEX] = v_addr; return 0; } - if (mc_get_version(&dpmng, CMD_PRI_LOW, &mc_ver_info)) { - DPAA2_BUS_ERR("Unable to obtain MC version"); - ret = -1; - goto cleanup; - } - - if ((mc_ver_info.major != MC_VER_MAJOR) || - (mc_ver_info.minor < MC_VER_MINOR)) { - DPAA2_BUS_ERR("DPAA2 MC version not compatible!" - " Expected %d.%d.x, Detected %d.%d.%d", - MC_VER_MAJOR, MC_VER_MINOR, - mc_ver_info.major, mc_ver_info.minor, - mc_ver_info.revision); - ret = -1; - goto cleanup; - } - rte_mcp_ptr_list[MC_PORTAL_INDEX] = (void *)v_addr; + rte_mcp_ptr_list[MC_PORTAL_INDEX] = v_addr; return 0; @@ -1537,237 +1562,6 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev) return ret; } -int -fslmc_vfio_close_group(void) -{ - struct rte_dpaa2_device *dev; - int vfio_group_fd; - const char *group_name = fslmc_vfio_get_group_name(); - - vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name); - if (vfio_group_fd <= 0) { - DPAA2_BUS_INFO("%s: Get fd by name(%s) failed(%d)", - __func__, group_name, vfio_group_fd); - if (vfio_group_fd < 0) - return vfio_group_fd; - return -EIO; - } - - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - if (dev->device.devargs && - dev->device.devargs->policy == RTE_DEV_BLOCKED) { - DPAA2_BUS_LOG(DEBUG, "%s Blacklisted, skipping", - dev->device.name); - rte_bus_remove_device(&rte_fslmc_bus, &dev->device); - continue; - } - switch (dev->dev_type) { - case DPAA2_ETH: - case DPAA2_CRYPTO: - case DPAA2_QDMA: - case DPAA2_IO: - fslmc_close_iodevices(dev, vfio_group_fd); - break; - case DPAA2_CON: - case DPAA2_CI: - case DPAA2_BPOOL: - case DPAA2_MUX: - if (rte_eal_process_type() == RTE_PROC_SECONDARY) - continue; - - fslmc_close_iodevices(dev, vfio_group_fd); - break; - case DPAA2_DPRTC: - default: - DPAA2_BUS_DEBUG("Device cannot be closed: Not supported (%s)", - dev->device.name); - } - } - - fslmc_vfio_clear_group(vfio_group_fd); - - return 0; -} - -int -fslmc_vfio_process_group(void) -{ - int ret; - int found_mportal = 0; - struct rte_dpaa2_device *dev; - bool is_dpmcp_in_blocklist = false, is_dpio_in_blocklist = false; - int dpmcp_count = 0, dpio_count = 0, current_device; - - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - if (dev->dev_type == DPAA2_MPORTAL) { - dpmcp_count++; - if (dev->device.devargs && - dev->device.devargs->policy == RTE_DEV_BLOCKED) - is_dpmcp_in_blocklist = true; - } - if (dev->dev_type == DPAA2_IO) { - dpio_count++; - if (dev->device.devargs && - dev->device.devargs->policy == RTE_DEV_BLOCKED) - is_dpio_in_blocklist = true; - } - } - - /* Search the MCP as that should be initialized first. */ - current_device = 0; - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - if (dev->dev_type == DPAA2_MPORTAL) { - current_device++; - if (dev->device.devargs && - dev->device.devargs->policy == RTE_DEV_BLOCKED) { - DPAA2_BUS_LOG(DEBUG, "%s Blocked, skipping", - dev->device.name); - rte_bus_remove_device(&rte_fslmc_bus, - &dev->device); - continue; - } - - if (rte_eal_process_type() == RTE_PROC_SECONDARY && - !is_dpmcp_in_blocklist) { - if (dpmcp_count == 1 || - current_device != dpmcp_count) { - rte_bus_remove_device(&rte_fslmc_bus, - &dev->device); - continue; - } - } - - if (!found_mportal) { - ret = fslmc_process_mcp(dev); - if (ret) { - DPAA2_BUS_ERR("Unable to map MC Portal"); - return ret; - } - found_mportal = 1; - } - - rte_bus_remove_device(&rte_fslmc_bus, &dev->device); - free(dev); - dev = NULL; - /* Ideally there is only a single dpmcp, but in case - * multiple exists, looping on remaining devices. - */ - } - } - - /* Cannot continue if there is not even a single mportal */ - if (!found_mportal) { - DPAA2_BUS_ERR("No MC Portal device found. Not continuing"); - return -EIO; - } - - /* Search for DPRC device next as it updates endpoint of - * other devices. - */ - current_device = 0; - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - if (dev->dev_type == DPAA2_DPRC) { - ret = fslmc_process_iodevices(dev); - if (ret) { - DPAA2_BUS_ERR("Unable to process dprc"); - return ret; - } - rte_bus_remove_device(&rte_fslmc_bus, &dev->device); - } - } - - current_device = 0; - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - if (dev->dev_type == DPAA2_IO) - current_device++; - if (dev->device.devargs && - dev->device.devargs->policy == RTE_DEV_BLOCKED) { - DPAA2_BUS_LOG(DEBUG, "%s Blocked, skipping", - dev->device.name); - rte_bus_remove_device(&rte_fslmc_bus, &dev->device); - continue; - } - if (rte_eal_process_type() == RTE_PROC_SECONDARY && - dev->dev_type != DPAA2_ETH && - dev->dev_type != DPAA2_CRYPTO && - dev->dev_type != DPAA2_QDMA && - dev->dev_type != DPAA2_IO) { - rte_bus_remove_device(&rte_fslmc_bus, &dev->device); - continue; - } - switch (dev->dev_type) { - case DPAA2_ETH: - case DPAA2_CRYPTO: - case DPAA2_QDMA: - ret = fslmc_process_iodevices(dev); - if (ret) { - DPAA2_BUS_DEBUG("Dev (%s) init failed", - dev->device.name); - return ret; - } - break; - case DPAA2_CON: - case DPAA2_CI: - case DPAA2_BPOOL: - case DPAA2_DPRTC: - case DPAA2_MUX: - /* IN case of secondary processes, all control objects - * like dpbp, dpcon, dpci are not initialized/required - * - all of these are assumed to be initialized and made - * available by primary. - */ - if (rte_eal_process_type() == RTE_PROC_SECONDARY) - continue; - - /* Call the object creation routine and remove the - * device entry from device list - */ - ret = fslmc_process_iodevices(dev); - if (ret) { - DPAA2_BUS_DEBUG("Dev (%s) init failed", - dev->device.name); - return ret; - } - - break; - case DPAA2_IO: - if (!is_dpio_in_blocklist && dpio_count > 1) { - if (rte_eal_process_type() == RTE_PROC_SECONDARY - && current_device != dpio_count) { - rte_bus_remove_device(&rte_fslmc_bus, - &dev->device); - break; - } - if (rte_eal_process_type() == RTE_PROC_PRIMARY - && current_device == dpio_count) { - rte_bus_remove_device(&rte_fslmc_bus, - &dev->device); - break; - } - } - - ret = fslmc_process_iodevices(dev); - if (ret) { - DPAA2_BUS_DEBUG("Dev (%s) init failed", - dev->device.name); - return ret; - } - - break; - case DPAA2_UNKNOWN: - default: - /* Unknown - ignore */ - DPAA2_BUS_DEBUG("Found unknown device (%s)", - dev->device.name); - rte_bus_remove_device(&rte_fslmc_bus, &dev->device); - free(dev); - dev = NULL; - } - } - - return 0; -} - int fslmc_vfio_setup_group(void) { @@ -1805,21 +1599,20 @@ fslmc_vfio_setup_group(void) if (ret) { DPAA2_BUS_ERR("VFIO(%s:fd=%d) error getting group status(%d)", group_name, vfio_group_fd, ret); - fslmc_vfio_clear_group(vfio_group_fd); + fslmc_vfio_clear_group(); return ret; } if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) { DPAA2_BUS_ERR("VFIO group not viable"); - fslmc_vfio_clear_group(vfio_group_fd); + fslmc_vfio_clear_group(); return -EPERM; } /* check if group does not have a container yet */ if (!(status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET)) { /* Now connect this IOMMU group to given container */ - ret = vfio_connect_container(vfio_container_fd, - vfio_group_fd); + ret = vfio_connect_container(vfio_container_fd, vfio_group_fd); } else { /* Here is supposed in secondary process, * group has been set to container in primary process. @@ -1830,7 +1623,7 @@ fslmc_vfio_setup_group(void) } if (ret) { DPAA2_BUS_ERR("vfio group connect failed(%d)", ret); - fslmc_vfio_clear_group(vfio_group_fd); + fslmc_vfio_clear_group(); return ret; } @@ -1838,14 +1631,14 @@ fslmc_vfio_setup_group(void) ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD, group_name); if (ret < 0) { DPAA2_BUS_ERR("Error getting device %s fd", group_name); - fslmc_vfio_clear_group(vfio_group_fd); + fslmc_vfio_clear_group(); return ret; } ret = fslmc_vfio_mp_sync_setup(); if (ret) { DPAA2_BUS_ERR("VFIO MP sync setup failed!"); - fslmc_vfio_clear_group(vfio_group_fd); + fslmc_vfio_clear_group(); return ret; } diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h index c995fd67b8..5403459a8b 100644 --- a/drivers/bus/fslmc/fslmc_vfio.h +++ b/drivers/bus/fslmc/fslmc_vfio.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019-2023 NXP + * Copyright 2016,2019-2026 NXP * */ @@ -9,40 +9,11 @@ #define _FSLMC_VFIO_H_ #include <rte_compat.h> +#include <rte_vfio.h> +#include <rte_interrupts.h> /* Pathname of FSL-MC devices directory. */ #define SYSFS_FSL_MC_DEVICES "/sys/bus/fsl-mc/devices" -#define DPAA2_MC_DPNI_DEVID 7 -#define DPAA2_MC_DPSECI_DEVID 3 -#define DPAA2_MC_DPCON_DEVID 5 -#define DPAA2_MC_DPIO_DEVID 9 -#define DPAA2_MC_DPBP_DEVID 10 -#define DPAA2_MC_DPCI_DEVID 11 - -struct fslmc_vfio_device { - LIST_ENTRY(fslmc_vfio_device) next; - int fd; /* fslmc root container device ?? */ - int index; /*index of child object */ - char dev_name[64]; - struct fslmc_vfio_device *child; /* Child object */ -}; - -struct fslmc_vfio_group { - LIST_ENTRY(fslmc_vfio_group) next; - int fd; /* /dev/vfio/"groupid" */ - int groupid; - int connected; - char group_name[64]; /* dprc.x*/ - int iommu_type; - LIST_HEAD(, fslmc_vfio_device) vfio_devices; -}; - -struct fslmc_vfio_container { - int fd; /* /dev/vfio/vfio */ - LIST_HEAD(, fslmc_vfio_group) groups; -}; - -extern char *fslmc_container; __rte_internal int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index); @@ -50,14 +21,9 @@ int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index); __rte_internal int rte_dpaa2_intr_disable(struct rte_intr_handle *intr_handle, int index); -int rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, - int vfio_dev_fd, - int num_irqs); +int rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, int vfio_dev_fd, + int num_irqs); + +int fslmc_vfio_core_cluster_sdest(uint32_t cpu_id); -int fslmc_vfio_setup_group(void); -int fslmc_vfio_process_group(void); -int fslmc_vfio_close_group(void); -char *fslmc_get_container(void); -int fslmc_get_container_group(const char *group_name, int *gropuid); -int fslmc_vfio_dmamap(void); #endif /* _FSLMC_VFIO_H_ */ diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c index 02b69d404d..2234da0975 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2021 NXP + * Copyright 2021, 2026 NXP * */ @@ -17,6 +17,7 @@ #include <mc/fsl_dprc.h> #include "portal/dpaa2_hw_pvt.h" +extern struct rte_bus rte_fslmc_bus; TAILQ_HEAD(dprc_dev_list, dpaa2_dprc_dev); static struct dprc_dev_list dprc_dev_list = TAILQ_HEAD_INITIALIZER(dprc_dev_list); /*!< DPRC device list */ diff --git a/drivers/bus/fslmc/private.h b/drivers/bus/fslmc/private.h index 20a454c3fc..841dc9c0c6 100644 --- a/drivers/bus/fslmc/private.h +++ b/drivers/bus/fslmc/private.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2016,2021 NXP + * Copyright 2016, 2021, 2026 NXP */ #ifndef BUS_FSLMC_PRIVATE_H @@ -9,6 +9,16 @@ #include <bus_fslmc_driver.h> -extern struct rte_bus rte_fslmc_bus; +int fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev); +int fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev); + +void fslmc_vfio_close_iodevices(struct rte_dpaa2_device *dev); + +int fslmc_vfio_setup_group(void); +void fslmc_vfio_clear_group(void); + +int fslmc_vfio_get_container_group(const char *group_name, int *gropuid); +int fslmc_vfio_dmamap(void); + #endif /* BUS_FSLMC_PRIVATE_H */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v4-S3 08/65] bus/fslmc: split bus-level device walk from VFIO primitives 2026-10-23 13:42 ` [PATCH v4-S3 08/65] bus/fslmc: split bus-level device walk from VFIO primitives Prashant Gupta @ 2026-10-23 15:00 ` David Marchand 0 siblings, 0 replies; 356+ messages in thread From: David Marchand @ 2026-10-23 15:00 UTC (permalink / raw) To: Prashant Gupta, Jun Yang, Hemant Agrawal; +Cc: stephen, dev, Thomas Monjalon On Fri, 23 Oct 2026 at 15:45, Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > > From: Jun Yang <jun.yang@nxp.com> > > The fslmc bus and its VFIO backend were tangled: VFIO-internal types > and DPAA2_MC_*_DEVID constants were exposed in a public header, and > the device-iteration / blocklist / primary-secondary policy for probe > and close lived inside fslmc_vfio.c (fslmc_vfio_process_group / > fslmc_vfio_close_group) even though it is pure bus logic. On top of > that, several bus-internal symbols were still declared with public > "fslmc_*" names. > > Signed-off-by: Jun Yang <jun.yang@nxp.com> https://patchwork.dpdk.org/project/dpdk/list/?series=39643 First version posted in July. https://patchwork.dpdk.org/project/dpdk/patch/20260723135400.3621271-10-david.marchand@redhat.com/ -- David Marchand ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v4-S3 09/65] bus/fslmc: centralize MC version and SoC detection in the bus layer 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (7 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 08/65] bus/fslmc: split bus-level device walk from VFIO primitives Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 10/65] net/dpaa2: remove unused soft parser loader Prashant Gupta ` (55 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> MC-version and SoC-version detection used to be split across several places and done lazily. That meant SoC-dependent globals were only populated after the first DPIO was created (anything running before that saw zero), the MC compatibility check sat in the VFIO mapping function (wrong layer), and the per-SoC table was hard-coded with magic numbers inside dpio.c. Collect it all once, at MCP map time, and publish it via a per-device rte_fslmc_bus_info handle. Benefits: - MC version and SoC identity are known as soon as the MCP is mapped, not lazily on first DPIO probe. Code paths that run before DPIO creation (e.g. memory pool / dma map / early dpaa2_svr_family-sensitive logic) now see valid values. - The MC compatibility check lives at the right layer and runs for both primary and secondary processes through a single code path. - Per-SoC quirks (cluster base/size, DQRR/EQCR ring sizes) are a single table lookup instead of magic numbers scattered across files; adding a new SoC becomes a one-line change. - Drivers get MC/SoC info via dpaa2_dev->bus_info and no longer need to call MC commands themselves (dpaa2_fw_version_get() is the first consumer). Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 11 +- drivers/bus/fslmc/fslmc_bus.c | 4 +- drivers/bus/fslmc/fslmc_vfio.c | 141 ++++++++++++++++++++++- drivers/bus/fslmc/fslmc_vfio.h | 24 ++++ drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 79 +------------ drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 9 +- drivers/bus/fslmc/private.h | 3 +- drivers/net/dpaa2/dpaa2_ethdev.c | 18 ++- drivers/net/dpaa2/dpaa2_ethdev.h | 1 + drivers/net/dpaa2/dpaa2_rxtx.c | 7 +- 10 files changed, 198 insertions(+), 99 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 44f81cf662..3ba865e632 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016,2021-2023 NXP + * Copyright 2016,2021-2026 NXP * */ @@ -89,6 +89,14 @@ enum rte_dpaa2_dev_type { DPAA2_DEVTYPE_MAX, }; +struct rte_fslmc_bus_info { + void *mem_pool; + int sp_protocol; + uint64_t mc_rev; + uint32_t svr; + uint32_t pvr; +}; + /** * A structure describing a DPAA2 device. */ @@ -102,6 +110,7 @@ struct rte_dpaa2_device { char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ + const struct rte_fslmc_bus_info *bus_info; }; typedef int (*rte_dpaa2_obj_create_t)(int vdev_fd, diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index 7116817c75..de7e9b78c1 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -29,6 +29,7 @@ struct rte_bus rte_fslmc_bus; static int fslmc_bus_device_count[DPAA2_DEVTYPE_MAX]; +static struct rte_fslmc_bus_info fslmc_bus_info; #define DPAA2_SEQN_DYNFIELD_NAME "dpaa2_seqn_dynfield" RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) @@ -199,6 +200,7 @@ scan_one_fslmc_device(char *dev_name) goto cleanup; } dev->device.devargs = rte_bus_find_devargs(&rte_fslmc_bus, dev_name); + dev->bus_info = &fslmc_bus_info; /* Update the device found into the device_count table */ fslmc_bus_device_count[dev->dev_type]++; @@ -429,7 +431,7 @@ fslmc_bus_process_iodevices(void) } if (!found_mportal) { - ret = fslmc_vfio_process_mcp(dev); + ret = fslmc_vfio_process_mcp(dev, &fslmc_bus_info); if (ret) { DPAA2_BUS_ERR("Unable to map MC Portal"); return ret; diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index 5b22e985b1..4897d7a78b 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -110,6 +110,83 @@ enum { FSLMC_VFIO_SOCKET_REQ_MEM }; +/* Variable to store DPAA2 platform type */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) +uint32_t dpaa2_svr_family; + +/* Variable to store DPAA2 DQRR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) +uint32_t dpaa2_dqrr_size; +/* Variable to store DPAA2 EQCR size */ +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) +uint32_t dpaa2_eqcr_size; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_base) +uint32_t dpaa2_cluster_base; +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_cluster_size) +uint32_t dpaa2_cluster_size; + +struct fslmc_soc_type { + uint32_t svr; + uint32_t cluster_base; + uint32_t cluster_size; + uint32_t qm_dq_size; + uint32_t qm_eq_size; +}; + +/* For LS208X platform There are four clusters with following mapping: + * Cluster 1 (ID = x04) : CPU0, CPU1; + * Cluster 2 (ID = x05) : CPU2, CPU3; + * Cluster 3 (ID = x06) : CPU4, CPU5; + * Cluster 4 (ID = x07) : CPU6, CPU7; + */ +/* For LS108X platform There are two clusters with following mapping: + * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; + * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; + */ +/* For LX2160 platform There are four clusters with following mapping: + * Cluster 1 (ID = x00) : CPU0, CPU1; + * Cluster 2 (ID = x01) : CPU2, CPU3; + * Cluster 3 (ID = x02) : CPU4, CPU5; + * Cluster 4 (ID = x03) : CPU6, CPU7; + * Cluster 1 (ID = x04) : CPU8, CPU9; + * Cluster 2 (ID = x05) : CPU10, CP11; + * Cluster 3 (ID = x06) : CPU12, CPU13; + * Cluster 4 (ID = x07) : CPU14, CPU15; + */ + +int +fslmc_vfio_core_cluster_sdest(uint32_t cpu_id) +{ + int x = cpu_id / dpaa2_cluster_size; + + if (!dpaa2_cluster_size) { + DPAA2_BUS_ERR("SoC type has not been initialized!"); + + return -ENODEV; + } + + return dpaa2_cluster_base + x; +} + +static const struct fslmc_soc_type s_soc_type[] = { + { + SVR_LS2080A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS2088A, 4, 2, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LS1080A, 2, 4, + DPAA2_DQRR_RING_SIZE, DPAA2_EQCR_RING_SIZE + }, + { + SVR_LX2160A, 0, 2, + DPAA2_LX2_DQRR_RING_SIZE, DPAA2_LX2_EQCR_RING_SIZE + } +}; + RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_get_mcp_ptr) void * dpaa2_get_mcp_ptr(int portal_idx) @@ -191,6 +268,63 @@ rte_fslmc_object_register(struct rte_dpaa2_object *object) TAILQ_INSERT_TAIL(&dpaa2_obj_list, object, next); } +static int +fslmc_vfio_get_bus_info(void *regs, struct rte_fslmc_bus_info *bus_info) +{ + struct fsl_mc_io mc_io; + struct mc_version mc_ver_info = {0}; + struct mc_soc_version mc_plat_info; + int ret; + size_t i; + + mc_io.regs = regs; + + ret = mc_get_version(&mc_io, CMD_PRI_LOW, &mc_ver_info); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to obtain MC version.", ret); + return ret; + } + DPAA2_BUS_INFO("MC version is %d.%d.%d.", mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + bus_info->mc_rev = RTE_FSL_MC_REV(mc_ver_info.major, + mc_ver_info.minor, mc_ver_info.revision); + + if (bus_info->mc_rev < RTE_FSL_MC_REV(MC_VER_MAJOR, MC_VER_MINOR, 0)) { + DPAA2_BUS_ERR("DPAA2 MC version not compatible! %d.%d.%d < %d.%d.0", + mc_ver_info.major, mc_ver_info.minor, mc_ver_info.revision, + MC_VER_MAJOR, MC_VER_MINOR); + return -EPERM; + } + + memset(&mc_plat_info, 0, sizeof(struct mc_soc_version)); + ret = mc_get_soc_version(&mc_io, CMD_PRI_LOW, &mc_plat_info); + if (ret) { + DPAA2_BUS_ERR("Unable to get SoC version err:%d", ret); + return ret; + } + + for (i = 0; i < RTE_DIM(s_soc_type); i++) { + if ((mc_plat_info.svr & DPAA2_SVR_MASK) == s_soc_type[i].svr) { + dpaa2_svr_family = s_soc_type[i].svr; + dpaa2_cluster_base = s_soc_type[i].cluster_base; + dpaa2_cluster_size = s_soc_type[i].cluster_size; + dpaa2_dqrr_size = s_soc_type[i].qm_dq_size; + dpaa2_eqcr_size = s_soc_type[i].qm_eq_size; + break; + } + } + if (i == RTE_DIM(s_soc_type)) { + DPAA2_BUS_ERR("Invalid SoC version: 0x%08x", mc_plat_info.svr); + return -ENODEV; + } + + bus_info->svr = mc_plat_info.svr; + bus_info->pvr = mc_plat_info.pvr; + + return 0; +} + static const char * fslmc_vfio_get_group_name(void) { @@ -1522,7 +1656,8 @@ fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev) } int -fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev) +fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev, + struct rte_fslmc_bus_info *bus_info) { int ret; void *v_addr; @@ -1541,6 +1676,10 @@ fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev) goto cleanup; } + ret = fslmc_vfio_get_bus_info(v_addr, bus_info); + if (ret) + goto cleanup; + /* In case of secondary processes, MC version check is no longer * required. */ diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h index 5403459a8b..34f2d7759c 100644 --- a/drivers/bus/fslmc/fslmc_vfio.h +++ b/drivers/bus/fslmc/fslmc_vfio.h @@ -15,6 +15,30 @@ /* Pathname of FSL-MC devices directory. */ #define SYSFS_FSL_MC_DEVICES "/sys/bus/fsl-mc/devices" +extern uint32_t dpaa2_svr_family; +extern uint32_t dpaa2_dqrr_size; +extern uint32_t dpaa2_eqcr_size; +extern uint32_t dpaa2_cluster_base; +extern uint32_t dpaa2_cluster_size; + +#define DPAA2_SVR_MASK 0xffff0000 + +#define SVR_LS1080A 0x87030000 +#define SVR_LS2080A 0x87010000 +#define SVR_LS2088A 0x87090000 +#define SVR_LX2160A 0x87360000 + +#define MC_MAJOR_OFFSET 32 +#define MC_MINOR_OFFSET 16 +#define MC_MINOR_MASK ((((uint64_t)1) << (MC_MAJOR_OFFSET - MC_MINOR_OFFSET)) - 1) +#define MC_REVISION_MASK ((((uint64_t)1) << MC_MINOR_OFFSET) - 1) +#define RTE_FSL_MC_REV(major, minor, revision) \ + ((((uint64_t)(major)) << MC_MAJOR_OFFSET) + \ + (((uint64_t)(minor)) << MC_MINOR_OFFSET) + (revision)) +#define RTE_FSL_MC_REV_MAJOR(rev) ((uint32_t)((rev) >> MC_MAJOR_OFFSET)) +#define RTE_FSL_MC_REV_MINOR(rev) ((uint32_t)(((rev) >> MC_MINOR_OFFSET) & MC_MINOR_MASK)) +#define RTE_FSL_MC_REV_REVISION(rev) ((uint32_t)((rev) & MC_REVISION_MASK)) + __rte_internal int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index); diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 9fe449ed38..b1443f327a 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2022 NXP + * Copyright 2016-2026 NXP * */ #include <uapi/linux/vfio.h> @@ -63,45 +63,9 @@ static struct dpio_dev_list dpio_dev_list = TAILQ_HEAD_INITIALIZER(dpio_dev_list); /*!< DPIO device list */ static uint32_t io_space_count; -/* Variable to store DPAA2 platform type */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_svr_family) -uint32_t dpaa2_svr_family; - -/* Variable to store DPAA2 DQRR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dqrr_size) -uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eqcr_size) -uint8_t dpaa2_eqcr_size; - /* Variable to hold the portal_key, once created.*/ static pthread_key_t dpaa2_portal_key; -/*Stashing Macros default for LS208x*/ -static int dpaa2_core_cluster_base = 0x04; -static int dpaa2_cluster_sz = 2; - -/* For LS208X platform There are four clusters with following mapping: - * Cluster 1 (ID = x04) : CPU0, CPU1; - * Cluster 2 (ID = x05) : CPU2, CPU3; - * Cluster 3 (ID = x06) : CPU4, CPU5; - * Cluster 4 (ID = x07) : CPU6, CPU7; - */ -/* For LS108X platform There are two clusters with following mapping: - * Cluster 1 (ID = x02) : CPU0, CPU1, CPU2, CPU3; - * Cluster 2 (ID = x03) : CPU4, CPU5, CPU6, CPU7; - */ -/* For LX2160 platform There are four clusters with following mapping: - * Cluster 1 (ID = x00) : CPU0, CPU1; - * Cluster 2 (ID = x01) : CPU2, CPU3; - * Cluster 3 (ID = x02) : CPU4, CPU5; - * Cluster 4 (ID = x03) : CPU6, CPU7; - * Cluster 1 (ID = x04) : CPU8, CPU9; - * Cluster 2 (ID = x05) : CPU10, CP11; - * Cluster 3 (ID = x06) : CPU12, CPU13; - * Cluster 4 (ID = x07) : CPU14, CPU15; - */ - static struct dpaa2_dpio_dev *get_dpio_dev_from_id(int32_t dpio_id) { struct dpaa2_dpio_dev *dpio_dev = NULL; @@ -141,14 +105,6 @@ dpaa2_get_core_id(void) return cpu_id; } -static int -dpaa2_core_cluster_sdest(int cpu_id) -{ - int x = cpu_id / dpaa2_cluster_sz; - - return dpaa2_core_cluster_base + x; -} - static void dpaa2_affine_dpio_intr_to_respective_core(int32_t dpio_id, int cpu_id) { @@ -307,15 +263,17 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx /* Set the STASH Destination depending on Current CPU ID. * Valid values of SDEST are 4,5,6,7. Where, */ - sdest = dpaa2_core_cluster_sdest(cpu_id); + sdest = fslmc_vfio_core_cluster_sdest(cpu_id); DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", dpio_dev->index, cpu_id, sdest); + if (sdest < 0) + return sdest; ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token, sdest); if (ret) { DPAA2_BUS_ERR("%d ERROR in SDEST", ret); - return -1; + return ret; } #ifdef RTE_EVENT_DPAA2 @@ -548,33 +506,6 @@ dpaa2_create_dpio_device(int vdev_fd, goto err; } - /* find the SoC type for the first time */ - if (!dpaa2_svr_family) { - struct mc_soc_version mc_plat_info = {0}; - - if (mc_get_soc_version(dpio_dev->dpio, - CMD_PRI_LOW, &mc_plat_info)) { - DPAA2_BUS_ERR("Unable to get SoC version information"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LS1080A) { - dpaa2_core_cluster_base = 0x02; - dpaa2_cluster_sz = 4; - DPAA2_BUS_DEBUG("LS108x (A53) Platform Detected"); - } else if ((mc_plat_info.svr & 0xffff0000) == SVR_LX2160A) { - dpaa2_core_cluster_base = 0x00; - dpaa2_cluster_sz = 2; - DPAA2_BUS_DEBUG("LX2160 Platform Detected"); - } - dpaa2_svr_family = (mc_plat_info.svr & 0xffff0000); - - if (dpaa2_svr_family == SVR_LX2160A) { - dpaa2_dqrr_size = DPAA2_LX2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_LX2_EQCR_RING_SIZE; - } else { - dpaa2_dqrr_size = DPAA2_DQRR_RING_SIZE; - dpaa2_eqcr_size = DPAA2_EQCR_RING_SIZE; - } - } - if (dpaa2_svr_family == SVR_LX2160A) reg_info.index = DPAA2_SWP_CENA_MEM_REGION; else diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 7e2271cc35..0838254437 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2023 NXP + * Copyright 2016-2023, 2026 NXP * */ @@ -35,13 +35,6 @@ RTE_DECLARE_PER_LCORE(struct dpaa2_io_portal_t, _dpaa2_io); #define DPAA2_PER_LCORE_DQRR_MBUF(i) \ RTE_PER_LCORE(_dpaa2_io).dpio_dev->dpaa2_held_bufs.mbuf[i] -/* Variable to store DPAA2 DQRR size */ -extern uint8_t dpaa2_dqrr_size; -/* Variable to store DPAA2 EQCR size */ -extern uint8_t dpaa2_eqcr_size; - -extern struct dpaa2_io_portal_t dpaa2_io_portal[RTE_MAX_LCORE]; - /* Affine a DPIO portal to current processing thread */ __rte_internal int dpaa2_affine_qbman_swp(void); diff --git a/drivers/bus/fslmc/private.h b/drivers/bus/fslmc/private.h index 841dc9c0c6..3586092529 100644 --- a/drivers/bus/fslmc/private.h +++ b/drivers/bus/fslmc/private.h @@ -9,7 +9,8 @@ #include <bus_fslmc_driver.h> -int fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev); +int fslmc_vfio_process_mcp(struct rte_dpaa2_device *dev, + struct rte_fslmc_bus_info *bus_info); int fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev); void fslmc_vfio_close_iodevices(struct rte_dpaa2_device *dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f697454d1a..b40f973c4d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -369,24 +369,21 @@ dpaa2_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size) { int ret; + uint32_t major, minor, rev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = dev->process_private; struct mc_soc_version mc_plat_info = {0}; - struct mc_version mc_ver_info = {0}; PMD_INIT_FUNC_TRACE(); + major = RTE_FSL_MC_REV_MAJOR(priv->mc_rev); + minor = RTE_FSL_MC_REV_MINOR(priv->mc_rev); + rev = RTE_FSL_MC_REV_REVISION(priv->mc_rev); if (mc_get_soc_version(dpni, CMD_PRI_LOW, &mc_plat_info)) DPAA2_PMD_WARN("\tmc_get_soc_version failed"); - if (mc_get_version(dpni, CMD_PRI_LOW, &mc_ver_info)) - DPAA2_PMD_WARN("\tmc_get_version failed"); - - ret = snprintf(fw_version, fw_size, - "%x-%d.%d.%d", - mc_plat_info.svr, - mc_ver_info.major, - mc_ver_info.minor, - mc_ver_info.revision); + ret = snprintf(fw_version, fw_size, "%x-%d.%d.%d", + mc_plat_info.svr, major, minor, rev); if (ret < 0) return -EINVAL; @@ -3521,6 +3518,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + priv->mc_rev = dpaa2_dev->bus_info->mc_rev; priv->num_rx_tc = attr.num_rx_tcs; priv->num_tx_tc = attr.num_tx_tcs; priv->qos_entries = attr.qos_entries; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 16e55412db..08d433a216 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -505,6 +505,7 @@ struct dpaa2_dev_priv { uint32_t *cnt_idx_dma_mem; uint64_t *cnt_values_dma_mem; uint64_t cnt_idx_iova, cnt_values_iova; + uint64_t mc_rev; struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 02494686d3..ebad66fd5e 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1149,7 +1149,8 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct dpaa2_queue *dpaa2_q = queue; struct qbman_result *dq_storage; uint32_t fqid = dpaa2_q->fqid; - int ret, num_rx = 0, next_pull = nb_pkts, num_pulled; + uint16_t num_rx = 0, next_pull = nb_pkts, num_pulled; + int ret; uint8_t pending, status; struct qbman_swp *swp; const struct qbman_fd *fd; @@ -1293,8 +1294,8 @@ uint16_t dpaa2_dev_tx_conf(void *queue) /* Function receive frames for a given device and VQ */ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; struct qbman_result *dq_storage; - uint32_t fqid = dpaa2_q->fqid; - int ret, num_tx_conf = 0, num_pulled; + uint32_t fqid = dpaa2_q->fqid, num_tx_conf = 0, num_pulled; + int ret; uint8_t pending, status; struct qbman_swp *swp; const struct qbman_fd *fd; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 10/65] net/dpaa2: remove unused soft parser loader 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (8 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 09/65] bus/fslmc: centralize MC version and SoC detection in the bus layer Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 11/65] net/dpaa2: cache per-rxq DPNI queue cfg and share CGID per TC Prashant Gupta ` (54 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed, together with dpaa2_sparser.c/.h and the DPAA2_ENABLE_SOFT_PARSER environment hook. Instead of trying to load an SP image, the presence of a soft parser protocol is now detected once from the WRIOP parser CCSR at bus scan time (fslmc_soft_parser_protocol_supported()) and exposed through priv->sp_protocol. The rte_flow pattern checks that previously relied on the run-time dpaa2_soft_parser_loaded() probe now consume priv->sp_protocol instead. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- drivers/bus/fslmc/fslmc_bus.c | 89 +++++++++++++ drivers/bus/fslmc/fslmc_logs.h | 2 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 +---- drivers/net/dpaa2/dpaa2_ethdev.h | 1 - drivers/net/dpaa2/dpaa2_flow.c | 114 +++-------------- drivers/net/dpaa2/dpaa2_recycle.c | 3 +- drivers/net/dpaa2/dpaa2_sparser.c | 137 -------------------- drivers/net/dpaa2/dpaa2_sparser.h | 202 ------------------------------ drivers/net/dpaa2/meson.build | 1 - 9 files changed, 107 insertions(+), 470 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index de7e9b78c1..a418f9a420 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -8,6 +8,7 @@ #include <dirent.h> #include <stdalign.h> #include <stdbool.h> +#include <sys/mman.h> #include <eal_export.h> #include <rte_log.h> @@ -35,6 +36,93 @@ static struct rte_fslmc_bus_info fslmc_bus_info; RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_seqn_dynfield_offset) int dpaa2_seqn_dynfield_offset = -1; +/** For LX2160A, LS2088A and LS1088A*/ +#define WRIOP_CCSR_BASE 0x8b80000 +#define WRIOP_CCSR_CTLU_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 +#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 + +#define WRIOP_INGRESS_PARSER_PHY \ + (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_OFFSET + \ + WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) + +struct __rte_packed_begin dpaa2_parser_ccsr { + uint32_t psr_cfg; + uint32_t psr_idle; + uint32_t psr_pclm; + uint8_t psr_ver_min; + uint8_t psr_ver_maj; + uint8_t psr_id1_l; + uint8_t psr_id1_h; + uint32_t psr_rev2; + uint8_t rsv[0x2c]; + uint8_t sp_ins[4032]; +} __rte_packed_end; + +#define SP_PROTOCOL_MAGIC_DATA 0xabcd +#define SP_PROTOCOL_MAGIC_OFFSET 0x4 + +/** Number of soft parser firmware bytes reported for debugging. */ +#define SP_PRINT_LEN 128 +/** Firmware bytes logged per debug line. */ +#define SP_DUMP_BYTES_PER_LINE 16 + +static void +fslmc_soft_parser_protocol_supported(void) +{ + int fd, i, pos = 0; + void *map_addr = NULL; + const struct dpaa2_parser_ccsr *parser_ccsr = NULL; + const uint16_t *magic_num; + char line[SP_DUMP_BYTES_PER_LINE * 3 + 1]; + + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd < 0) { + DPAA2_BUS_ERR("open \"/dev/mem\" ERROR(%d)", fd); + goto exit; + } + + map_addr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), + PROT_READ | PROT_WRITE, MAP_SHARED, fd, + WRIOP_INGRESS_PARSER_PHY); + if (map_addr == MAP_FAILED) { + DPAA2_BUS_ERR("Map 0x%" PRIx64 "(size=0x%zx) failed", + (uint64_t)WRIOP_INGRESS_PARSER_PHY, + sizeof(struct dpaa2_parser_ccsr)); + map_addr = NULL; + goto exit; + } + parser_ccsr = map_addr; + + DPAA2_BUS_DEBUG("Soft ParserID:0x%02x%02x, Rev:maj(%02x), min(%02x)", + parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, + parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); + + magic_num = (const void *)&parser_ccsr->sp_ins[SP_PROTOCOL_MAGIC_OFFSET]; + if (*magic_num == SP_PROTOCOL_MAGIC_DATA) { + fslmc_bus_info.sp_protocol = true; + DPAA2_BUS_NOTICE("Soft parser protocol support."); + DPAA2_BUS_NOTICE("First %d bytes of sp protocol firmware:", SP_PRINT_LEN); + for (i = 0; i < SP_PRINT_LEN; i++) { + pos += snprintf(&line[pos], sizeof(line) - pos, + "%02x ", parser_ccsr->sp_ins[i]); + if ((i + 1) % SP_DUMP_BYTES_PER_LINE == 0) { + DPAA2_BUS_NOTICE("%s", line); + pos = 0; + } + } + if (pos) + DPAA2_BUS_NOTICE("%s", line); + } + +exit: + if (map_addr) + munmap(map_addr, sizeof(struct dpaa2_parser_ccsr)); + if (fd >= 0) + close(fd); +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_get_device_count) uint32_t rte_fslmc_get_device_count(enum rte_dpaa2_dev_type device_type) @@ -345,6 +433,7 @@ rte_fslmc_scan(void) DPAA2_BUS_ERR("Unable to open VFIO group directory"); goto scan_fail; } + fslmc_soft_parser_protocol_supported(); /* Scan the DPRC container object */ ret = scan_one_fslmc_device(group_name); diff --git a/drivers/bus/fslmc/fslmc_logs.h b/drivers/bus/fslmc/fslmc_logs.h index 412d160d11..7e27ca4bf4 100644 --- a/drivers/bus/fslmc/fslmc_logs.h +++ b/drivers/bus/fslmc/fslmc_logs.h @@ -19,6 +19,8 @@ extern int dpaa2_logtype_bus; #define DPAA2_BUS_INFO(fmt, ...) \ DPAA2_BUS_LOG(INFO, fmt, ## __VA_ARGS__) +#define DPAA2_BUS_NOTICE(fmt, ...) \ + DPAA2_BUS_LOG(NOTICE, fmt, ## __VA_ARGS__) #define DPAA2_BUS_ERR(fmt, ...) \ DPAA2_BUS_LOG(ERR, fmt, ## __VA_ARGS__) #define DPAA2_BUS_WARN(fmt, ...) \ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index b40f973c4d..195cc922dc 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <dpaax_devarg.h> @@ -3688,33 +3687,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } + priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 08d433a216..5d98c56fa4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -637,7 +637,6 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); -int dpaa2_soft_parser_loaded(void); void dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index d9ca7211c7..8e65faf75d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -9,7 +9,6 @@ #include <string.h> #include <unistd.h> #include <stdarg.h> -#include <sys/mman.h> #include <rte_ethdev.h> #include <rte_log.h> @@ -22,9 +21,9 @@ #include <dpaa2_ethdev.h> #include <dpaa2_pmd_logs.h> +#include "dpaa2_parser_decode.h" static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -434,92 +433,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -4730,7 +4643,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, static int dpaa2_flow_item_convert(const struct rte_flow_item pattern[], - struct rte_dpaa2_flow_item **dpaa2_pattern) + struct rte_dpaa2_flow_item **dpaa2_pattern, int sp_protocol) { struct rte_dpaa2_flow_item *new_pattern; int num = 0, tunnel_start = 0; @@ -4742,7 +4655,7 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], } new_pattern = rte_malloc(NULL, sizeof(struct rte_dpaa2_flow_item) * num, - RTE_CACHE_LINE_SIZE); + RTE_CACHE_LINE_SIZE); if (!new_pattern) { DPAA2_PMD_ERR("Failed to alloc %d flow items", num); return -ENOMEM; @@ -4750,13 +4663,13 @@ dpaa2_flow_item_convert(const struct rte_flow_item pattern[], num = 0; while (pattern[num].type != RTE_FLOW_ITEM_TYPE_END) { - memcpy(&new_pattern[num].generic_item, &pattern[num], - sizeof(struct rte_flow_item)); + rte_memcpy(&new_pattern[num].generic_item, &pattern[num], + sizeof(struct rte_flow_item)); new_pattern[num].in_tunnel = 0; if (pattern[num].type == RTE_FLOW_ITEM_TYPE_VXLAN) tunnel_start = 1; - else if (tunnel_start) + else if (tunnel_start && sp_protocol) new_pattern[num].in_tunnel = 1; num++; } @@ -4793,7 +4706,8 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, if (ret) return ret; - ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern); + ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, + priv->sp_protocol); if (ret) return ret; @@ -5134,9 +5048,10 @@ dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, } static inline int -dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) +dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], + int sp_support) { - unsigned int i, j, is_found = 0; + uint32_t i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; const enum rte_flow_item_type *sp_supported; @@ -5158,7 +5073,7 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) } if (is_found) continue; - if (dpaa2_sp_loaded > 0) { + if (sp_support) { for (i = 0; i < sp_supported_num; i++) { if (sp_supported[i] == pattern[j].type) { is_found = 1; @@ -5167,8 +5082,7 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) } } if (!is_found) { - DPAA2_PMD_WARN("Flow type(%d) not supported", - pattern[j].type); + DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); ret = -ENOTSUP; break; } @@ -5237,7 +5151,7 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, goto not_valid_params; } /* Verify input pattern list */ - ret = dpaa2_dev_verify_patterns(pattern); + ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol); if (ret < 0) { DPAA2_PMD_ERR("Invalid pattern list is given"); rte_flow_error_set(error, EPERM, diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..48b531d847 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2019-2021 NXP + * Copyright 2019-2026 NXP */ #include <time.h> @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..b821f7bfad 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -16,7 +16,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 11/65] net/dpaa2: cache per-rxq DPNI queue cfg and share CGID per TC 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (9 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 10/65] net/dpaa2: remove unused soft parser loader Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 12/65] The dpaa2 PMD so far supported only two Tx buffer release schemes: direct release by hardware, and an absolute Tx confirmation mode (drv_tx_conf=1) where every transmitted buffer is returned on a Tx confirmation queue that software must poll to free the buffers. Absolute confirmation adds a confirmation descriptor and a poll cost for all packets, even those the hardware could free on its own Prashant Gupta ` (53 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rework DPAA2 Rx queue setup so the DPNI queue descriptor is allocated once per Rx queue and reused on later reconfiguration (eventq attach / detach, release), and change congestion-group (CGID) allocation from one CGID per Rx queue to one CGID shared by all Rx queues of the same traffic class. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 3 +- drivers/net/dpaa2/dpaa2_ethdev.c | 269 ++++++++++++------------ drivers/net/dpaa2/dpaa2_ethdev.h | 3 +- 3 files changed, 134 insertions(+), 141 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 52f4434928..48a465c206 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -177,7 +177,6 @@ struct __rte_cache_aligned dpaa2_queue { uint32_t fqid; /*!< Unique ID of this queue */ uint16_t flow_id; /*!< To be used by DPAA2 framework */ uint8_t tc_index; /*!< traffic class identifier */ - uint8_t cgid; /*! < Congestion Group id for this queue */ uint64_t rx_pkts; uint64_t tx_pkts; uint64_t err_pkts; @@ -187,6 +186,8 @@ struct __rte_cache_aligned dpaa2_queue { /**Egress*/ struct qbman_result *cscn; }; + void *cfg; + uint8_t options; struct rte_event ev; dpaa2_queue_cb_dqrr_t *cb; dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 195cc922dc..0e515d560e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -721,6 +721,9 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) RTE_MAX_LCORE); dpaa2_queue_storage_free(dpaa2_q, RTE_MAX_LCORE); + if (dpaa2_q->cfg) + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; priv->rx_vq[i] = NULL; } /* cleanup tx queue cscn */ @@ -971,13 +974,13 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = dev->process_private; - bool dpcon_allocated = false; struct dpaa2_queue *dpaa2_q; - struct dpni_queue cfg; - uint8_t options = 0; - uint8_t flow_id; + struct dpni_queue *cfg = NULL; + struct dpni_taildrop taildrop; + uint8_t qopt = 0; + uint16_t flow_id; uint32_t bpid; - int i, ret; + int ret; PMD_INIT_FUNC_TRACE(); @@ -1014,6 +1017,10 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; } + cfg = rte_zmalloc(NULL, sizeof(struct dpni_queue), 0); + if (!cfg) + return -ENOMEM; + dpaa2_q->cfg = cfg; dpaa2_q->mb_pool = mb_pool; /**< mbuf pool to populate RX ring. */ dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; @@ -1028,148 +1035,124 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->napi_dpcon = rte_dpaa2_alloc_dpcon_dev(); if (!dpaa2_q->napi_dpcon) { DPAA2_PMD_ERR("rxq %d: no DPCON for rx-queue interrupts", - rx_queue_id); - return -ENODEV; + rx_queue_id); + ret = -ENODEV; + goto err_quit; } - dpcon_allocated = true; /* the DPCON must be enabled to generate CDAN notifications */ ret = dpcon_enable(&dpaa2_q->napi_dpcon->dpcon, CMD_PRI_LOW, - dpaa2_q->napi_dpcon->token); + dpaa2_q->napi_dpcon->token); if (ret) { DPAA2_PMD_ERR("rxq %d: dpcon_enable: %d", rx_queue_id, ret); - goto err_free_dpcon; + goto err_quit; } } /*Get the flow id from given VQ id*/ flow_id = dpaa2_q->flow_id; - memset(&cfg, 0, sizeof(struct dpni_queue)); + memset(cfg, 0, sizeof(struct dpni_queue)); - options = options | DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_q); + qopt |= DPNI_QUEUE_OPT_USER_CTX; + cfg->user_context = (size_t)(dpaa2_q); /* napi: schedule the FQ to its DPCON once, when the channel is first * grabbed; never re-bound (the MC refuses scheduled->parked at runtime) */ - if (dpcon_allocated) { - options |= DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpaa2_q->napi_dpcon->dpcon_id; - } - - /* check if a private cgr available. */ - for (i = 0; i < priv->max_cgs; i++) { - if (!priv->cgid_in_use[i]) { - priv->cgid_in_use[i] = 1; - break; - } + if (dpaa2_q->napi_dpcon) { + qopt |= DPNI_QUEUE_OPT_DEST; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpaa2_q->napi_dpcon->dpcon_id; } - if (i < priv->max_cgs) { - options |= DPNI_QUEUE_OPT_SET_CGID; - cfg.cgid = i; - dpaa2_q->cgid = cfg.cgid; + /** RXQs in same TC share same cgid.*/ + if (dpaa2_q->tc_index < priv->max_cgs) { + qopt |= DPNI_QUEUE_OPT_SET_CGID; + cfg->cgid = dpaa2_q->tc_index; + priv->cgid_in_use[dpaa2_q->tc_index]++; } else { - dpaa2_q->cgid = DPAA2_INVALID_CGID; + cfg->cgid = DPAA2_INVALID_CGID; } /*if ls2088 or rev2 device, enable the stashing */ if ((dpaa2_svr_family & 0xffff0000) != SVR_LS2080A) { - options |= DPNI_QUEUE_OPT_FLC; - cfg.flc.stash_control = true; - dpaa2_flc_stashing_clear_all(&cfg.flc.value); + qopt |= DPNI_QUEUE_OPT_FLC; + cfg->flc.stash_control = true; + dpaa2_flc_stashing_clear_all(&cfg->flc.value); if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 1; } else { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); dpaa2_q->data_stashing_off = 0; } if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, 1, - &cfg.flc.value); + &cfg->flc.value); } } + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, options, &cfg); + dpaa2_q->tc_index, flow_id, qopt, cfg); if (ret) { DPAA2_PMD_ERR("Error in setting the rx flow: = %d", ret); - goto err_free_dpcon; + goto err_quit; } dpaa2_q->nb_desc = nb_rx_desc; - - if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) { - struct dpni_taildrop taildrop; - + memset(&taildrop, 0, sizeof(struct dpni_taildrop)); + if (!(priv->flags & DPAA2_RX_TAILDROP_OFF)) taildrop.enable = 1; - /* Private CGR will use tail drop length as nb_rx_desc. - * for rest cases we can use standard byte based tail drop. - * There is no HW restriction, but number of CGRs are limited, - * hence this restriction is placed. - */ - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - /*enabling per rx queue congestion control */ - taildrop.threshold = nb_rx_desc; - taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; - taildrop.oal = 0; - DPAA2_PMD_DEBUG("Enabling CG Tail Drop on queue = %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - /*enabling per rx queue congestion control */ - taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; - taildrop.units = DPNI_CONGESTION_UNIT_BYTES; - taildrop.oal = CONG_RX_OAL; - DPAA2_PMD_DEBUG("Enabling Byte based Drop on queue= %d", - rx_queue_id); - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, - &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } - } else { /* Disable tail Drop */ - struct dpni_taildrop taildrop = {0}; - DPAA2_PMD_INFO("Tail drop is disabled on queue"); - - taildrop.enable = 0; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, - dpaa2_q->tc_index, - dpaa2_q->cgid, &taildrop); - } else { - ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, - DPNI_CP_QUEUE, DPNI_QUEUE_RX, - dpaa2_q->tc_index, flow_id, &taildrop); - } - if (ret) { - DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", - ret); - goto err_free_dpcon; - } + /* Private CGR will use tail drop length as nb_rx_desc * queues per TC. + * For rest cases we can use standard byte based tail drop. + * There is no HW restriction, but number of CGRs are limited, + * hence this restriction is placed. + */ + if (cfg->cgid != DPAA2_INVALID_CGID && + priv->cgid_in_use[dpaa2_q->tc_index] == 1) { + /*enabling per TC congestion control */ + taildrop.threshold = nb_rx_desc * priv->dist_queues; + taildrop.units = DPNI_CONGESTION_UNIT_FRAMES; + taildrop.oal = 0; + DPAA2_PMD_DEBUG("%s CG Tail Drop on TC%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX, + dpaa2_q->tc_index, cfg->cgid, &taildrop); + } else if (cfg->cgid == DPAA2_INVALID_CGID) { + /*enabling per rx queue congestion control */ + taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q; + taildrop.units = DPNI_CONGESTION_UNIT_BYTES; + taildrop.oal = CONG_RX_OAL; + DPAA2_PMD_DEBUG("%s Byte based Drop on TC[%d].flow%d", + taildrop.enable ? "Enabling" : "Disabling", + dpaa2_q->tc_index, flow_id); + ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token, + DPNI_CP_QUEUE, DPNI_QUEUE_RX, + dpaa2_q->tc_index, flow_id, &taildrop); } + if (ret) { + DPAA2_PMD_ERR("Error in setting taildrop. err=(%d)", ret); + goto err_quit; + } + + dpaa2_q->options = qopt; dev->data->rx_queues[rx_queue_id] = dpaa2_q; return 0; -err_free_dpcon: +err_quit: + if (dpaa2_q->cfg) { + rte_free(dpaa2_q->cfg); + dpaa2_q->cfg = NULL; + } /* free only the DPCON this call allocated; a pre-existing one belongs to * an earlier setup and is released at dev_close */ - if (dpcon_allocated) { + if (dpaa2_q->napi_dpcon) { rte_dpaa2_free_dpcon_dev(dpaa2_q->napi_dpcon); dpaa2_q->napi_dpcon = NULL; } @@ -1189,8 +1172,8 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct fsl_mc_io *dpni = dev->process_private; struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; - uint8_t options = 0, flow_id; - uint16_t channel_id; + uint8_t qopt = 0; + uint16_t channel_id, flow_id; struct dpni_queue_id qid; uint32_t tc_id; int ret; @@ -1220,7 +1203,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, channel_id = priv->tx_channels[priv->num_channels - 1]; ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, - DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, options, &tx_flow_cfg); + DPNI_BUILD_PARAM(channel_id, tc_id), flow_id, qopt, &tx_flow_cfg); if (ret) { DPAA2_PMD_ERR("Failed(%d) to set %s's TC[%d].txq[%d]", ret, dev->data->name, tc_id, flow_id); @@ -1229,7 +1212,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, &tx_flow_cfg, &qid); + dpaa2_q->flow_id, &tx_flow_cfg, &qid); if (ret) { DPAA2_PMD_ERR("Error in getting LFQID err=%d", ret); return ret; @@ -1281,12 +1264,12 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; - options = options | DPNI_QUEUE_OPT_USER_CTX; + qopt |= DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_TX_CONFIRM, DPNI_BUILD_PARAM(channel_id, tc_id), - flow_id, options, &tx_conf_cfg); + flow_id, qopt, &tx_conf_cfg); if (ret) { DPAA2_PMD_ERR("Set TC[%d].TX[%d] conf flow err=%d", tc_id, flow_id, ret); @@ -1335,30 +1318,29 @@ dpaa2_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id) struct dpaa2_queue *dpaa2_q = dev->data->rx_queues[rx_queue_id]; struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; struct fsl_mc_io *dpni = priv->eth_dev->process_private; - uint8_t options = 0; + uint8_t qopt = 0; int ret; - struct dpni_queue cfg; + struct dpni_queue *cfg = dpaa2_q->cfg; - memset(&cfg, 0, sizeof(struct dpni_queue)); PMD_INIT_FUNC_TRACE(); total_nb_rx_desc -= dpaa2_q->nb_desc; - if (dpaa2_q->cgid != DPAA2_INVALID_CGID) { - options = DPNI_QUEUE_OPT_CLEAR_CGID; - cfg.cgid = dpaa2_q->cgid; - - ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX, - dpaa2_q->tc_index, dpaa2_q->flow_id, - options, &cfg); - if (ret) - DPAA2_PMD_ERR("Unable to clear CGR from q=%u err=%d", - dpaa2_q->fqid, ret); - priv->cgid_in_use[dpaa2_q->cgid] = 0; - dpaa2_q->cgid = DPAA2_INVALID_CGID; + if (cfg) { + if (cfg->cgid != DPAA2_INVALID_CGID) { + qopt = DPNI_QUEUE_OPT_CLEAR_CGID; + ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, + DPNI_QUEUE_RX, dpaa2_q->tc_index, dpaa2_q->flow_id, + qopt, cfg); + if (ret) { + DPAA2_PMD_ERR("Unable to clear CGR from TC[%d].flow%d err=%d", + dpaa2_q->tc_index, dpaa2_q->flow_id, ret); + } + priv->cgid_in_use[cfg->cgid]--; + } + rte_free(cfg); + dpaa2_q->cfg = NULL; } - /* keep the DPCON on the FQ across a reconfigure; freed at dev_close */ if (dpaa2_q->napi_dpcon) dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); @@ -2875,10 +2857,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; + struct dpni_queue *cfg; uint8_t options, priority; int ret; + cfg = dpaa2_ethq->cfg; + if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_PARALLEL) dpaa2_ethq->cb = dpaa2_dev_process_parallel_event; else if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) @@ -2891,15 +2875,19 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, priority = (RTE_EVENT_DEV_PRIORITY_LOWEST / queue_conf->ev.priority) * (dpcon->num_priorities - 1); - memset(&cfg, 0, sizeof(struct dpni_queue)); + if (!cfg) { + DPAA2_PMD_ERR("%s: %s-rxq%d was not setup yet!", + __func__, dev->data->name, eth_rx_queue_id); + return -EINVAL; + } options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_DPCON; - cfg.destination.id = dpcon->dpcon_id; - cfg.destination.priority = priority; + cfg->destination.type = DPNI_DEST_DPCON; + cfg->destination.id = dpcon->dpcon_id; + cfg->destination.priority = priority; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) { options |= DPNI_QUEUE_OPT_HOLD_ACTIVE; - cfg.destination.hold_active = 1; + cfg->destination.hold_active = 1; } if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED && @@ -2938,16 +2926,16 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, } options |= DPNI_QUEUE_OPT_USER_CTX; - cfg.user_context = (size_t)(dpaa2_ethq); + cfg->user_context = (size_t)(dpaa2_ethq); ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, flow_id, options, cfg); if (ret) { DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); return ret; } - memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); + rte_memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); return 0; } @@ -2959,17 +2947,15 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; - struct dpni_queue cfg; - uint8_t options; + struct dpni_queue *cfg; int ret; - memset(&cfg, 0, sizeof(struct dpni_queue)); - options = DPNI_QUEUE_OPT_DEST; - cfg.destination.type = DPNI_DEST_NONE; + cfg = dpaa2_ethq->cfg; + cfg->destination.type = DPNI_DEST_NONE; + dpaa2_ethq->options &= ~DPNI_QUEUE_OPT_DEST; ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, &cfg); + dpaa2_ethq->tc_index, dpaa2_ethq->flow_id, dpaa2_ethq->options, cfg); if (ret) DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); @@ -3528,10 +3514,15 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ - if (attr.options & DPNI_OPT_CUSTOM_CG) + if (attr.options & DPNI_OPT_CUSTOM_CG) { priv->max_cgs = attr.num_cgs; - else + if (priv->max_cgs < priv->num_rx_tc) { + DPAA2_PMD_WARN("DPNI%d has no enough cgids(%d) to set %d TCs", + hw_id, priv->max_cgs, priv->num_rx_tc); + } + } else { priv->max_cgs = 0; + } for (i = 0; i < priv->max_cgs; i++) priv->cgid_in_use[i] = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 5d98c56fa4..55027d6afb 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -460,7 +460,8 @@ struct dpaa2_dev_priv { uint8_t en_ordered; uint8_t en_loose_ordered; uint8_t max_cgs; - uint8_t cgid_in_use[MAX_RX_QUEUES]; + /** RXQs in same TC share same cgid.*/ + uint8_t cgid_in_use[MAX_TCS]; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 12/65] The dpaa2 PMD so far supported only two Tx buffer release schemes: direct release by hardware, and an absolute Tx confirmation mode (drv_tx_conf=1) where every transmitted buffer is returned on a Tx confirmation queue that software must poll to free the buffers. Absolute confirmation adds a confirmation descriptor and a poll cost for all packets, even those the hardware could free on its own. 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (10 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 11/65] net/dpaa2: cache per-rxq DPNI queue cfg and share CGID per TC Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 13/65] net/dpaa2: support runtime IEEE1588 timestamping Prashant Gupta ` (52 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add a dynamic Tx confirmation mode in which only the buffers that the hardware cannot release directly (for example indirect, external or shared buffers) are returned on the Tx confirmation queue, while ordinary buffers from the known hardware pool are still freed by the hardware. This keeps the fast path cheap and limits confirmation polling to the cases that actually need it. The mode is enabled with the new device argument drv_tx_dyn_conf=1. The Tx path is reworked to build either a simple or a scatter-gather FD with per-buffer confirmation decided at enqueue time (dpaa2_dev_tx_mbuf_to_simple_fd / dpaa2_dev_tx_mbuf_to_sg_fd and the confirm/no-confirm SGE helpers), the FAEAD is programmed accordingly (dpaa2_dev_tx_config_dynamic_confirm), and dpaa2_dev_tx_conf() drains the confirmation queue and frees only the buffers that were handed back. The Rx FD-to-mbuf helpers are exported so the confirmation path can reuse them. Documentation and the device argument string are updated for the new option. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- doc/guides/nics/dpaa2.rst | 11 +- drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 2 +- drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h | 6 +- drivers/net/dpaa2/dpaa2_ethdev.c | 67 +- drivers/net/dpaa2/dpaa2_ethdev.h | 27 +- drivers/net/dpaa2/dpaa2_ptp.c | 6 +- drivers/net/dpaa2/dpaa2_rxtx.c | 1436 ++++++++---------- 7 files changed, 683 insertions(+), 872 deletions(-) diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index 60ca695f59..4480a5f652 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -476,10 +476,17 @@ Refer to the document :doc:`build_and_test` for details. of the packet pull command which is issued in the previous cycle. e.g. ``fslmc:dpni.1,drv_no_prefetch=1`` -* Use dev arg option ``drv_tx_conf=1`` to enable TX confirmation mode. - In this mode tx conf queues need to be polled to free the buffers. +* Use dev arg option ``drv_tx_conf=1`` to enable absolute TX confirmation mode. + In this mode every transmitted buffer is returned on a tx conf queue which + needs to be polled to free the buffers. e.g. ``fslmc:dpni.1,drv_tx_conf=1`` +* Use dev arg option ``drv_tx_dyn_conf=1`` to enable dynamic TX confirmation + mode. In this mode only buffers that cannot be released directly by the + hardware (for example indirect, external or shared buffers) are returned on + a tx conf queue which needs to be polled to free the buffers. + e.g. ``fslmc:dpni.1,drv_tx_dyn_conf=1`` + * Use dev arg option ``drv_rx_parse_drop=1`` to configure the system to start dropping the error packets in hardware (parse errors). e.g. ``fslmc:dpni.1,drv_rx_parse_drop=1`` diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c index 83694133f1..5f4268f0d7 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c @@ -482,7 +482,7 @@ dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, */ /* ... rx buffer layout ... */ - if (priv->flags & DPAA2_TX_DYNAMIC_CONF_ENABLE) { + if (priv->tx_conf_type == DPAA2_TX_DYNAMIC_CONF) { int out_min_hdr_room, in_min_hdr_room; /** Additional headroom layout for IPSec with TX configure * dynamic enabled. diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h index a670098958..b06fa3f644 100644 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h +++ b/drivers/net/dpaa2/base/dpaa2_hw_dpni_annot.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016,2019,2022,2024 NXP + * Copyright 2016,2019,2022,2024-2026 NXP * */ @@ -281,6 +281,10 @@ struct dpaa2_faead { /*UPD (Update prepended data)*/ #define DPAA2_ANNOT_FAEAD_UPD 0x00000010 +#define DPAA2_TX_CONFIRM_ENABLE \ + (DPAA2_ANNOT_FAEAD_A4V | DPAA2_ANNOT_FAEAD_EBDD | \ + DPAA2_ANNOT_FAEAD_EBDDV) + /* Debug frame, otherwise supposed to be discarded */ #define DPAA2_ETH_FAS_DISC 0x80000000 /* MACSEC frame */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0e515d560e..f4ed12f45a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -38,6 +38,29 @@ static const struct rte_mbuf_dynfield s_dpaa2_rx_protocol_pos_dyn = { .align = __alignof__(struct dpaa2_dyn_rx_protocol_pos), }; +#define DRIVER_TX_CONF "drv_tx_conf" +#define DRIVER_TX_DYNAMIC_CONF "drv_tx_dyn_conf" + +static void +dpaa2_dev_args_set_tx_conf(void *vdev, + const struct rte_kvargs_pair *pair) +{ + struct rte_eth_dev *dev = vdev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int val = pair->value ? atoi(pair->value) : 0; + + if (!strcmp(DRIVER_TX_CONF, pair->key) && val) { + priv->tx_conf_type = DPAA2_TX_ABSOLUTE_CONF; + } else if (!strcmp(DRIVER_TX_DYNAMIC_CONF, pair->key) && val) { + priv->tx_conf_type = DPAA2_TX_DYNAMIC_CONF; + } else { + priv->tx_conf_type = DPAA2_TX_NO_CONF; + return; + } + + DPAA2_PMD_INFO("%s Enabled", pair->key); +} + static void dpaa2_dev_args_parser_offset_en(void *vdev, const struct rte_kvargs_pair *pair) @@ -68,7 +91,8 @@ dpaa2_dev_args_parser_offset_en(void *vdev, #define DPAA2_DEVARGS(ENTRY) \ ENTRY("drv_loopback", NULL, DPAA2_RX_LOOPBACK_MODE) \ ENTRY("drv_no_prefetch", NULL, DPAA2_NO_PREFETCH_RX) \ - ENTRY("drv_tx_conf", NULL, DPAA2_TX_CONF_ENABLE) \ + ENTRY(DRIVER_TX_CONF, dpaa2_dev_args_set_tx_conf, 0) \ + ENTRY(DRIVER_TX_DYNAMIC_CONF, dpaa2_dev_args_set_tx_conf, 0) \ ENTRY("drv_rx_parse_drop", NULL, DPAA2_PARSE_ERR_DROP) \ ENTRY("drv_rx_print_parser_result", NULL, DPAA2_RX_PRINT_PSR_RESULT_FLAG) \ ENTRY("drv_err_queue", NULL, DPAA2_RX_ERROR_QUEUE_FLAG) \ @@ -561,7 +585,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (priv->flags & DPAA2_TX_CONF_ENABLE) + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) tot_queues = priv->nb_rx_queues + 2 * priv->nb_tx_queues; else tot_queues = priv->nb_rx_queues + priv->nb_tx_queues; @@ -617,7 +641,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) } } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /*Setup tx confirmation queues*/ for (i = 0; i < priv->nb_tx_queues; i++) { mc_q->eth_data = dev->data; @@ -732,7 +756,7 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) rte_free(dpaa2_q->cscn); priv->tx_vq[i] = NULL; } - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { /* cleanup tx conf queue storage */ for (i = 0; i < priv->nb_tx_queues; i++) { dpaa2_q = priv->tx_conf_vq[i]; @@ -1181,6 +1205,13 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, PMD_INIT_FUNC_TRACE(); + /* Tx deferred start is not supported */ + if (tx_conf->tx_deferred_start) { + DPAA2_PMD_ERR("%s:Tx deferred start not supported", + dev->data->name); + return -EINVAL; + } + dpaa2_q->nb_desc = UINT16_MAX; dpaa2_q->offloads = tx_conf->offloads; @@ -1260,7 +1291,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->cb_eqresp_free = dpaa2_dev_free_eqresp_buf; dev->data->tx_queues[tx_queue_id] = dpaa2_q; - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; @@ -3579,7 +3610,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) for (i = 0; i < priv->num_channels; i++) { /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) { ret = dpni_set_tx_confirmation_mode(dpni_dev, CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); } else { @@ -3616,34 +3647,22 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) /* ... tx buffer layout ... */ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | - DPNI_BUF_LAYOUT_OPT_TIMESTAMP; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; layout.pass_timestamp = true; - } else { - layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; } + layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX, &layout); + DPNI_QUEUE_TX, &layout); if (ret) { DPAA2_PMD_ERR("Error (%d) in setting tx buffer layout", ret); goto init_err; } - - /* ... tx-conf and error buffer layout ... */ - memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; - layout.pass_timestamp = true; - } - layout.options |= DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; - layout.pass_frame_status = 1; ret = dpni_set_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_TX_CONFIRM, &layout); + DPNI_QUEUE_TX_CONFIRM, &layout); if (ret) { - DPAA2_PMD_ERR("Error (%d) in setting tx-conf buffer layout", - ret); + DPAA2_PMD_ERR("Error (%d) in setting tx conf buffer layout", ret); goto init_err; } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 55027d6afb..28d6eb04ac 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -95,20 +95,12 @@ #define DPAA2_TX_DPNI_LOOPBACK_MODE RTE_BIT32(7) -/* Tx confirmation enabled */ -#define DPAA2_TX_CONF_ENABLE RTE_BIT32(8) - -/* Tx dynamic confirmation enabled, - * only valid with Tx confirmation enabled. - */ -#define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) - /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(8) -#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(9) -#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(10) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -433,6 +425,12 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +enum dpaa2_tx_conf_type { + DPAA2_TX_NO_CONF, + DPAA2_TX_ABSOLUTE_CONF, + DPAA2_TX_DYNAMIC_CONF +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -448,6 +446,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + enum dpaa2_tx_conf_type tx_conf_type; uint32_t psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; @@ -487,10 +486,10 @@ struct dpaa2_dev_priv { /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; - /* stores pointer to next tx_conf queue that should be processed, + /* stores next tx queue to be confirmed that should be processed, * it corresponds to last packet transmitted */ - struct dpaa2_queue *next_tx_conf_queue; + struct dpaa2_queue *next_txq_to_cnf; struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; @@ -621,7 +620,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); -uint16_t dpaa2_dev_tx_conf(void *queue) __rte_unused; +uint16_t dpaa2_dev_tx_conf(void *txq, int drain); int dpaa2_timesync_enable(struct rte_eth_dev *dev); int dpaa2_timesync_disable(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index 751e558c73..2863cad4dd 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2019, 2023 NXP + * Copyright 2019, 2023-2026 NXP */ #include <sys/queue.h> @@ -111,9 +111,9 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; - if (priv->next_tx_conf_queue) { + if (priv->next_txq_to_cnf) { while (!priv->tx_timestamp) - dpaa2_dev_tx_conf(priv->next_tx_conf_queue); + dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); } else { return -1; } diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index ebad66fd5e..24631b16c5 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -133,6 +133,24 @@ rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, DPAA2_RESET_FD_FLC(_fd); \ } while (0) +/* Build a contiguous FD which is returned on the Tx confirmation queue. + * The buffer is not released by the hardware, so an invalid buffer pool + * ID is programmed and the mbuf is carried in the FLC to be freed once + * the confirmation is dequeued. + */ +static inline void +dpaa2_mbuf_to_conf_contig_fd(struct rte_mbuf *mbuf, struct qbman_fd *fd) +{ + DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(mbuf)); + DPAA2_SET_FD_LEN(fd, mbuf->data_len); + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + DPAA2_SET_FD_OFFSET(fd, mbuf->data_off); + DPAA2_SET_FD_FRC(fd, 0); + DPAA2_RESET_FD_CTRL(fd); + DPAA2_SET_FD_FLC(fd, mbuf); +} + static inline void dpaa2_dev_rx_mbuf_flc_offload(struct rte_mbuf *m, const struct qbman_fd *fd) @@ -247,13 +265,6 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, "(4)=0x%" PRIx64 "\t", annotation->word3, annotation->word4); -#if defined(RTE_LIBRTE_IEEE1588) - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) { - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; - mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST; - } -#endif - if (BIT_ISSET_AT_POS(annotation->word3, L2_VLAN_1_PRESENT)) { vlan_tci = rte_pktmbuf_mtod_offset(mbuf, uint16_t *, (VLAN_TCI_OFFSET_1(annotation->word5) >> 16)); @@ -394,9 +405,9 @@ static inline struct rte_mbuf *__rte_hot dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; - size_t sg_addr, fd_addr; + size_t fd_addr; int i = 0, is_vlan = false; - void *hw_annot_addr; + void *hw_annot_addr, *sg_addr; struct rte_mbuf *first_seg, *next_seg, *cur_seg, *temp; if (unlikely(dpaa2_svr_family == SVR_LX2160A && @@ -410,7 +421,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) sgt = (struct qbman_sge *)(fd_addr + DPAA2_GET_FD_OFFSET(fd)); sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); /* First Scatter gather entry */ first_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, @@ -438,7 +449,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) cur_seg = first_seg; while (!DPAA2_SG_IS_FINAL(sge) && i < DPAA2_MAX_SGS) { sge = &sgt[i++]; - sg_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); + sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); next_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, rte_dpaa2_bpid_info[DPAA2_GET_FLE_BPID(sge)].meta_data_size); next_seg->buf_addr = (uint8_t *)sg_addr; @@ -521,119 +532,259 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return mbuf; } +static inline struct rte_mbuf * +dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) +{ + struct rte_mbuf *mc = rte_pktmbuf_alloc(mp); + + if (!mc) + return NULL; + if ((mc->data_off + sgm->data_len) > mc->buf_len) { + rte_pktmbuf_free(mc); + return NULL; + } + rte_memcpy(rte_pktmbuf_mtod(mc, void *), + rte_pktmbuf_mtod(sgm, void *), sgm->data_len); + mc->pkt_len = sgm->data_len; + mc->data_len = sgm->data_len; + mc->next = NULL; + + return mc; +} + +static inline void +dpaa2_dev_tx_config_dynamic_confirm(struct qbman_fd *fd, + struct dpaa2_queue *txq, int enable) +{ + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + + DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | DPAA2_FD_FRC_FAEADV); + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + if (enable) { + fd_faead->fqid = txq->tx_conf_queue->fqid; + fd_faead->ctrl = DPAA2_TX_CONFIRM_ENABLE; + } else { + fd_faead->fqid = 0; + fd_faead->ctrl &= (~DPAA2_TX_CONFIRM_ENABLE); + } +} + +static int +dpaa2_dev_tx_no_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf, + struct rte_mempool *hw_mp) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg, *mi, *prev, *copy_mbuf; + + cur_seg = mbuf; + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + mi = rte_mbuf_from_indirect(cur_seg); + if (rte_mbuf_refcnt_read(mi) > 1) + rte_mbuf_refcnt_update(mi, -1); + else + rte_pktmbuf_free_seg(mi); + copy_mbuf->next = cur_seg->next; + if (prev) + prev->next = copy_mbuf; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + if (unlikely(RTE_MBUF_HAS_EXTBUF(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index)) { + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(cur_seg, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + + copy_mbuf->next = cur_seg->next; + + if (prev) + prev->next = copy_mbuf; + if (rte_mbuf_refcnt_read(cur_seg) > 1) + rte_mbuf_refcnt_update(cur_seg, -1); + else + rte_pktmbuf_free_seg(cur_seg); + cur_seg = copy_mbuf; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + if (unlikely(rte_mbuf_refcnt_read(cur_seg) > 1)) { + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + rte_mbuf_refcnt_update(cur_seg, -1); + } else { + DPAA2_SET_FLE_BPID(sge, mempool_to_bpid(cur_seg->pool)); + } + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); + + return 0; +} + +static void +dpaa2_dev_tx_conf_mbuf_to_sge(struct qbman_sge *sgt, + struct rte_mbuf *mbuf, uint16_t nb_segs, struct rte_mbuf *sg_mbuf) +{ + int i; + struct qbman_sge *sge = NULL; + struct rte_mbuf *cur_seg = mbuf, *mi, *prev; + + prev = NULL; + for (i = 0; i < nb_segs; i++) { + sge = &sgt[i]; + /*Resetting the buffer pool id and offset field*/ + sge->fin_bpid_offset = 0; + if (unlikely(RTE_MBUF_CLONED(cur_seg))) { + mi = rte_mbuf_from_indirect(cur_seg); + mi->next = cur_seg->next; + if (prev) + prev->next = mi; + rte_pktmbuf_init(cur_seg->pool, NULL, cur_seg, 0); + rte_pktmbuf_free_seg(cur_seg); + cur_seg = mi; + } + DPAA2_SET_FLE_ADDR(sge, DPAA2_MBUF_VADDR_TO_IOVA(cur_seg)); + DPAA2_SET_FLE_OFFSET(sge, cur_seg->data_off); + DPAA2_SET_FLE_LEN(sge, cur_seg->data_len); + DPAA2_SET_FLE_BPID(sge, MAX_BPID); + DPAA2_SET_FLE_IVP(sge); + if (sg_mbuf == cur_seg) + DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); + prev = cur_seg; + cur_seg = cur_seg->next; + } + + if (likely(sge)) + DPAA2_SG_SET_FINAL(sge, true); +} + static int __rte_noinline __rte_hot -eth_mbuf_to_sg_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *free_buf, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf) { - struct rte_mbuf *cur_seg = mbuf, *mi, *temp; - struct qbman_sge *sgt, *sge = NULL; - int i, offset = 0; + struct rte_mbuf *cur_seg = mbuf, *sg_mbuf; + struct qbman_sge *sgt; + int offset = 0, ret, need_dyconf = false, need_conf = false; + uint16_t nb_segs = mbuf->nb_segs; + uint32_t sg_size = nb_segs * sizeof(struct qbman_sge); + struct rte_mempool *mp; -#ifdef RTE_LIBRTE_IEEE1588 - /* annotation area for timestamp in first buffer */ - offset = 0x64; -#endif - if (RTE_MBUF_DIRECT(mbuf) && - (mbuf->data_off > (mbuf->nb_segs * sizeof(struct qbman_sge) - + offset))) { - temp = mbuf; - if (rte_mbuf_refcnt_read(temp) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - fd->simple.bpid_offset = 0; + if (conf == DPAA2_TX_DYNAMIC_CONF) { + while (cur_seg) { + if (!RTE_MBUF_DIRECT(cur_seg) || + cur_seg->pool->ops_index != hw_mp->ops_index || + rte_mbuf_refcnt_read(cur_seg) > 1) { + need_dyconf = true; + break; + } + cur_seg = cur_seg->next; + } + cur_seg = mbuf; + } + if (need_dyconf || conf == DPAA2_TX_ABSOLUTE_CONF) + need_conf = true; + + if (need_dyconf) + offset = DPAA2_FD_PTA_SIZE + DPAA2_DYN_TX_MIN_FD_OFFSET; + + if (mbuf->pool->ops_index == hw_mp->ops_index && + RTE_MBUF_DIRECT(mbuf) && + mbuf->data_off > RTE_ALIGN(sg_size + offset, 8)) { + sg_mbuf = mbuf; + mp = mbuf->pool; + if (need_conf) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); DPAA2_SET_FD_IVP(fd); - rte_mbuf_refcnt_update(temp, -1); } else { - DPAA2_SET_ONLY_FD_BPID(fd, bpid); + if (unlikely(rte_mbuf_refcnt_read(sg_mbuf) > 1)) { + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + rte_mbuf_refcnt_update(sg_mbuf, -1); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(mp)); + } + } #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif - } DPAA2_SET_FD_OFFSET(fd, offset); } else { - temp = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); - if (temp == NULL) { + sg_mbuf = NULL; + if (dpaa2_tx_sg_pool) + sg_mbuf = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); + if (!sg_mbuf) { DPAA2_PMD_DP_DEBUG("No memory to allocate S/G table"); return -ENOMEM; } - DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); - DPAA2_SET_FD_OFFSET(fd, temp->data_off); + if (need_conf) { + if (need_dyconf) + sg_mbuf->data_off = RTE_ALIGN(offset, 8); + else + sg_mbuf->data_off = RTE_PKTMBUF_HEADROOM; + DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); + DPAA2_SET_FD_IVP(fd); + } else { + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); + } + DPAA2_SET_FD_OFFSET(fd, sg_mbuf->data_off); + offset = sg_mbuf->data_off; #ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)temp), - (void **)&temp, 1, 0); + rte_mempool_check_cookies(rte_mempool_from_obj(sg_mbuf), + (void **)&sg_mbuf, 1, 0); #endif } - DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(temp)); + + /*Set Scatter gather table and Scatter gather entries*/ + sgt = (void *)((size_t)sg_mbuf->buf_addr + offset); + DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(sg_mbuf)); DPAA2_SET_FD_LEN(fd, mbuf->pkt_len); DPAA2_FD_SET_FORMAT(fd, qbman_fd_sg); DPAA2_RESET_FD_FRC(fd); DPAA2_RESET_FD_CTRL(fd); - DPAA2_RESET_FD_FLC(fd); - /*Set Scatter gather table and Scatter gather entries*/ - sgt = (struct qbman_sge *)( - (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) - + DPAA2_GET_FD_OFFSET(fd)); + if (need_conf) + DPAA2_SET_FD_FLC(fd, sg_mbuf); + else + DPAA2_RESET_FD_FLC(fd); + if (need_dyconf) + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true); - for (i = 0; i < mbuf->nb_segs; i++) { - sge = &sgt[i]; - /*Resetting the buffer pool id and offset field*/ - sge->fin_bpid_offset = 0; - DPAA2_SET_FLE_ADDR(sge, rte_pktmbuf_iova(cur_seg)); - sge->length = cur_seg->data_len; - if (RTE_MBUF_DIRECT(cur_seg)) { - /* if we are using inline SGT in same buffers - * set the FLE FMT as Frame Data Section - */ - if (temp == cur_seg) { - DPAA2_SG_SET_FORMAT(sge, qbman_fd_list); - DPAA2_SET_FLE_IVP(sge); - } else { - if (rte_mbuf_refcnt_read(cur_seg) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - rte_mbuf_refcnt_update(cur_seg, -1); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(cur_seg->pool)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)cur_seg), - (void **)&cur_seg, 1, 0); -#endif - } - } - } else if (RTE_MBUF_HAS_EXTBUF(cur_seg)) { - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FLE_IVP(sge); - } else { - /* Get owner MBUF from indirect buffer */ - mi = rte_mbuf_from_indirect(cur_seg); - if (rte_mbuf_refcnt_read(mi) > 1) { - /* If refcnt > 1, invalid bpid is set to ensure - * owner buffer is not freed by HW - */ - DPAA2_SET_FLE_IVP(sge); - } else { - DPAA2_SET_FLE_BPID(sge, - mempool_to_bpid(mi->pool)); - rte_mbuf_refcnt_update(mi, 1); - } - free_buf[*free_count].seg = cur_seg; - free_buf[*free_count].pkt_id = pkt_id; - ++*free_count; - } - cur_seg = cur_seg->next; + if (cur_seg != sg_mbuf && need_conf) + sg_mbuf->next = cur_seg; + + if (need_conf) { + dpaa2_dev_tx_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, sg_mbuf); + } else { + ret = dpaa2_dev_tx_no_conf_mbuf_to_sge(sgt, cur_seg, nb_segs, + sg_mbuf, hw_mp); + if (ret) + return ret; } - DPAA2_SG_SET_FINAL(sge, true); + if (dy_conf && need_dyconf) + *dy_conf = true; + return 0; } @@ -654,101 +805,54 @@ dpaa2_dev_prefetch_next_psr(const struct qbman_result *dq) rte_prefetch0(&annotation->word3); } -static void -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) __rte_unused; - -static void __rte_noinline __rte_hot -eth_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, - struct sw_buf_free *buf_to_free, - uint32_t *free_count, - uint32_t pkt_id, - uint16_t bpid) +static int __rte_noinline __rte_hot +dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, + struct rte_mbuf *mbuf, struct qbman_fd *fd, + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, + uint8_t *dy_conf) { - DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, bpid); + int need_dyconf = false, need_conf = false; + struct rte_mbuf *mi; + struct rte_mbuf *copy_mbuf; + int ret = 0; - DPAA2_PMD_DP_DEBUG("mbuf =%p, mbuf->buf_addr =%p, off = %d," - "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", - mbuf, mbuf->buf_addr, mbuf->data_off, - DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd)); - if (RTE_MBUF_DIRECT(mbuf)) { + if (unlikely(RTE_MBUF_CLONED(mbuf))) { + mi = rte_mbuf_from_indirect(mbuf); if (rte_mbuf_refcnt_read(mbuf) > 1) { - DPAA2_SET_FD_IVP(fd); rte_mbuf_refcnt_update(mbuf, -1); + } else { + rte_pktmbuf_init(mbuf->pool, NULL, mbuf, 0); + rte_pktmbuf_free(mbuf); } -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - else - rte_mempool_check_cookies(rte_mempool_from_obj((void *)mbuf), - (void **)&mbuf, 1, 0); -#endif - } else if (RTE_MBUF_HAS_EXTBUF(mbuf)) { - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; - DPAA2_SET_FD_IVP(fd); + mbuf = mi; + } + if (conf == DPAA2_TX_DYNAMIC_CONF && + (mbuf->pool->ops_index != hw_mp->ops_index || + RTE_MBUF_HAS_EXTBUF(mbuf) || + rte_mbuf_refcnt_read(mbuf) > 1)) + need_dyconf = true; + if (conf == DPAA2_TX_ABSOLUTE_CONF || need_dyconf) + need_conf = true; + + if (need_conf) { + dpaa2_mbuf_to_conf_contig_fd(mbuf, fd); + } else if (mbuf->pool->ops_index == hw_mp->ops_index) { + DPAA2_MBUF_TO_CONTIG_FD(mbuf, fd, mempool_to_bpid(mbuf->pool)); } else { - struct rte_mbuf *mi; - - mi = rte_mbuf_from_indirect(mbuf); - if (rte_mbuf_refcnt_read(mi) > 1) - DPAA2_SET_FD_IVP(fd); - else - rte_mbuf_refcnt_update(mi, 1); - - buf_to_free[*free_count].seg = mbuf; - buf_to_free[*free_count].pkt_id = pkt_id; - ++*free_count; + copy_mbuf = dpaa2_dev_mbuf_copy_one_seg(mbuf, hw_mp); + if (!copy_mbuf) + return -ENOMEM; + DPAA2_MBUF_TO_CONTIG_FD(copy_mbuf, fd, mempool_to_bpid(hw_mp)); + rte_pktmbuf_free(mbuf); } -} - -static inline int __rte_hot -eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf, - struct qbman_fd *fd, uint16_t bpid) -{ - struct rte_mbuf *m; - void *mb = NULL; - if (rte_dpaa2_mbuf_alloc_bulk( - rte_dpaa2_bpid_info[bpid].bp_list->mp, &mb, 1)) { - DPAA2_PMD_DP_DEBUG("Unable to allocated DPAA2 buffer"); - return -1; + if (need_dyconf) { + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true); + if (dy_conf) + *dy_conf = true; } - m = (struct rte_mbuf *)mb; - memcpy((char *)m->buf_addr + mbuf->data_off, - (void *)((char *)mbuf->buf_addr + mbuf->data_off), - mbuf->pkt_len); - - /* Copy required fields */ - m->data_off = mbuf->data_off; - m->ol_flags = mbuf->ol_flags; - m->packet_type = mbuf->packet_type; - m->tx_offload = mbuf->tx_offload; - DPAA2_MBUF_TO_CONTIG_FD(m, fd, bpid); - -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies(rte_mempool_from_obj((void *)m), - (void **)&m, 1, 0); -#endif - DPAA2_PMD_DP_DEBUG( - "mbuf: %p, BMAN buf addr: %p, fdaddr: %" PRIx64 ", bpid: %d," - " meta: %d, off: %d, len: %d", - (void *)mbuf, - mbuf->buf_addr, - DPAA2_GET_FD_ADDR(fd), - DPAA2_GET_FD_BPID(fd), - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, - DPAA2_GET_FD_OFFSET(fd), - DPAA2_GET_FD_LEN(fd)); - -return 0; + return ret; } static void @@ -832,7 +936,6 @@ dpaa2_dev_rx_err_pkts_dump(struct dpaa2_queue *dpaa2_q) dpaa2_dev_rx_parse_offset(priv, mbuf, fd); dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); - DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd), @@ -1253,12 +1356,6 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1289,151 +1386,204 @@ dpaa2_dev_rx_channel(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) return dpaa2_dev_rx_common(queue, bufs, nb_pkts, true); } -uint16_t dpaa2_dev_tx_conf(void *queue) +static inline int +dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, + struct rte_mbuf *mbuf) { - /* Function receive frames for a given device and VQ */ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct qbman_result *dq_storage; - uint32_t fqid = dpaa2_q->fqid, num_tx_conf = 0, num_pulled; - int ret; - uint8_t pending, status; + while (mbuf) { + if (mbuf->pool != mp) + return false; + mbuf = mbuf->next; + } + + return true; +} + +uint16_t dpaa2_dev_tx_conf(void *txq, int drain) +{ + /* Function receive frames for a given device and VQ*/ + struct dpaa2_queue *dpaa2_txq = txq; + struct dpaa2_queue *dpaa2_q = dpaa2_txq->tx_conf_queue; + struct qbman_result *dq_storage, *dq_storage1 = NULL; + uint32_t fqid = dpaa2_q->fqid; + int ret, pull_size, total = 0, bulk_free; + uint8_t pending, status, idx, buf_idx; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; - struct qbman_release_desc releasedesc; - uint32_t bpid; - uint64_t buf; -#if defined(RTE_LIBRTE_IEEE1588) - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_annot_hdr *annotation; - void *v_addr; - struct rte_mbuf *mbuf; -#endif + struct queue_storage_info_t *q_storage; + struct qbman_result *rst; - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); + struct rte_mbuf *mbufs[dpaa2_dqrr_size]; + struct rte_mempool *mp = NULL; + #define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + +conf_again: + bulk_free = true; + idx = 0; + q_storage = dpaa2_q->q_storage[rte_lcore_id()]; + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); + DPAA2_PMD_ERR("Failure in affining portal"); return 0; } } - swp = DPAA2_PER_LCORE_PORTAL; - do { - dq_storage = dpaa2_q->q_storage[0]->dq_storage[0]; + swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + pull_size = dpaa2_dqrr_size; + if (unlikely(!q_storage->active_dqs)) { + q_storage->toggle = 0; + dq_storage = q_storage->dq_storage[q_storage->toggle]; + q_storage->last_num_pkts = pull_size; qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, + q_storage->last_num_pkts); qbman_pull_desc_set_fq(&pulldesc, fqid); qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - - qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size); - + DPAA2_VADDR_TO_IOVA(dq_storage), 1); + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } while (1) { if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued." - "QBMAN is busy"); + DPAA2_PMD_DP_DEBUG("QBMAN is busy (1)"); /* Portal was busy, try again */ continue; } break; } + q_storage->active_dqs = dq_storage; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage); + } - rte_prefetch0((void *)((size_t)(dq_storage + 1))); - /* Check if the previous issued command is completed. */ - while (!qbman_check_command_complete(dq_storage)) - ; + dq_storage = q_storage->active_dqs; + rte_prefetch0((void *)(dq_storage)); + rte_prefetch0((void *)(dq_storage + 1)); - num_pulled = 0; - pending = 1; - do { - /* Loop until the dq_storage is updated with - * new token by QBMAN - */ - while (!qbman_check_new_result(dq_storage)) - ; - rte_prefetch0((void *)((size_t)(dq_storage + 2))); - /* Check whether Last Pull command is Expired and - * setting Condition for Loop termination - */ - if (qbman_result_DQ_is_pull_complete(dq_storage)) { - pending = 0; - /* Check for valid frame. */ - status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & - QBMAN_DQ_STAT_VALIDFRAME) == 0)) - continue; - } - if (dpaa2_svr_family != SVR_LX2160A) - /** Packet type is parsed from FRC for LX2160A.*/ - dpaa2_dev_prefetch_next_psr(dq_storage); + /* Prepare next pull descriptor. This will give space for the + * prefetching done on DQRR entries + */ + q_storage->toggle ^= 1; + dq_storage1 = q_storage->dq_storage[q_storage->toggle]; + qbman_pull_desc_clear(&pulldesc); + qbman_pull_desc_set_numframes(&pulldesc, pull_size); + qbman_pull_desc_set_fq(&pulldesc, fqid); + qbman_pull_desc_set_storage(&pulldesc, dq_storage1, + DPAA2_VADDR_TO_IOVA(dq_storage1), 1); - fd = qbman_result_DQ_fd(dq_storage); - bpid = DPAA2_GET_FD_BPID(fd); + /* Check if the previous issued command is completed. + * Also seems like the SWP is shared between the Ethernet Driver + * and the SEC driver. + */ + while (!qbman_check_command_complete(dq_storage)) + ; + if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id)) + clear_swp_active_dqs(q_storage->active_dpio_id); - /* Create a release descriptor required for releasing - * buffers into QBMAN - */ - qbman_release_desc_clear(&releasedesc); - qbman_release_desc_set_bpid(&releasedesc, bpid); + pending = 1; - buf = DPAA2_GET_FD_ADDR(fd); - /* feed them to bman */ - do { - ret = qbman_swp_release(swp, &releasedesc, - &buf, 1); - } while (ret == -EBUSY); + do { + /* Loop until the dq_storage is updated with + * new token by QBMAN + */ + while (!qbman_check_new_result(dq_storage)) + ; + rte_prefetch0((void *)(dq_storage + 2)); + /* Check whether Last Pull command is Expired and + * setting Condition for Loop termination + */ + if (qbman_result_DQ_is_pull_complete(dq_storage)) { + pending = 0; + /* Check for valid frame. */ + status = qbman_result_DQ_flags(dq_storage); + if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) + continue; + } - dq_storage++; - num_tx_conf++; - num_pulled++; -#if defined(RTE_LIBRTE_IEEE1588) - v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); - mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); - - if (mbuf->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - annotation = (struct dpaa2_annot_hdr *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE); - priv->tx_timestamp = annotation->word2; - } -#endif - } while (pending); + fd = qbman_result_DQ_fd(dq_storage); + mbufs[idx] = (void *)DPAA2_GET_FD_FLC(fd); + if (unlikely(!mp)) + mp = mbufs[idx]->pool; + if (unlikely(rte_mbuf_refcnt_read(mbufs[idx]) > 1)) + bulk_free = false; + if (bulk_free && + !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) + bulk_free = false; + idx++; + dq_storage++; + if (idx >= dpaa2_dqrr_size) + break; + } while (pending); - /* Last VDQ provided all packets and more packets are requested */ - } while (num_pulled == dpaa2_dqrr_size); + if (check_swp_active_dqs(swp_idx)) { + rst = get_swp_active_dqs(swp_idx); + while (!qbman_check_command_complete(rst)) + ; + clear_swp_active_dqs(swp_idx); + } + /* issue a volatile dequeue command for next pull */ + while (1) { + if (qbman_swp_pull(swp, &pulldesc)) { + DPAA2_PMD_DP_DEBUG("QBMAN is busy (2)"); + continue; + } + break; + } + q_storage->active_dqs = dq_storage1; + q_storage->active_dpio_id = swp_idx; + set_swp_active_dqs(swp_idx, dq_storage1); - dpaa2_q->rx_pkts += num_tx_conf; + if (bulk_free) { + rte_pktmbuf_free_bulk(mbufs, idx); + } else { + for (buf_idx = 0; buf_idx < idx; buf_idx++) + rte_pktmbuf_free(mbufs[buf_idx]); + } + + dpaa2_q->rx_pkts += idx; + total += idx; + if (drain && pending) + goto conf_again; - return num_tx_conf; + return total; } -#ifdef RTE_LIBRTE_IEEE1588 -/* Configure the egress frame annotation for timestamp update */ -static void enable_tx_tstamp(struct qbman_fd *fd) +static inline int +dpaa2_dev_tx_fast_mbuf_to_fd(struct rte_eth_dev_data *dev, + struct rte_mbuf *buf, struct qbman_fd *fd, + enum dpaa2_tx_conf_type conf) { - struct dpaa2_faead *fd_faead; - - /* Set frame annotation status field as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FASV; - - /* Set frame annotation egress action descriptor as valid */ - (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; - - /* Set Annotation Length as 128B */ - (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + struct rte_mempool *mp = buf->pool; + struct dpaa2_dev_priv *priv = dev->dev_private; + + if (likely(RTE_MBUF_DIRECT(buf) && + mp && mp->ops_index == + priv->bp_list->dpaa2_ops_index && + buf->nb_segs == 1 && + rte_mbuf_refcnt_read(buf) == 1)) { + if (unlikely(buf->next)) { + DPAA2_PMD_WARN("Single mbuf has next segment(%p)", + buf->next); + } + if (unlikely(conf == DPAA2_TX_ABSOLUTE_CONF)) + dpaa2_mbuf_to_conf_contig_fd(buf, fd); + else + DPAA2_MBUF_TO_CONTIG_FD(buf, fd, mempool_to_bpid(mp)); +#ifdef RTE_LIBRTE_MEMPOOL_DEBUG + rte_mempool_check_cookies(rte_mempool_from_obj(buf), + (void **)&buf, 1, 0); +#endif + return 0; + } - /* enable update of confirmation frame annotation */ - fd_faead = (struct dpaa2_faead *)((size_t) - DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) + - DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); - fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | - DPAA2_ANNOT_FAEAD_UPD; + return -EAGAIN; } -#endif + /* * Callback to handle sending packets through WRIOP based interface */ @@ -1441,28 +1591,24 @@ uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ - uint32_t loop, retry_count; + uint32_t loop, retry_count, i; int32_t ret; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; uint32_t frames_to_send; - struct rte_mempool *mp; struct qbman_eq_desc eqdesc; - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; + struct dpaa2_queue *dpaa2_q = queue; struct qbman_swp *swp; uint16_t num_tx = 0; - uint16_t bpid; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct rte_mempool *hw_mp; uint32_t flags[MAX_TX_RING_SLOTS] = {0}; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } @@ -1470,19 +1616,17 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) swp = DPAA2_PER_LCORE_PORTAL; DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); + eth_data, dpaa2_q->fqid); -#ifdef RTE_LIBRTE_IEEE1588 - /* IEEE1588 driver need pointer to tx confirmation queue - * corresponding to last packet transmitted for reading - * the timestamp - */ - if ((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) { - priv->next_tx_conf_queue = dpaa2_q->tx_conf_queue; - dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue); - priv->tx_timestamp = 0; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + return 0; } -#endif + hw_mp = priv->bp_list->mp; + + if (dpaa2_q->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q, false); /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc); @@ -1490,214 +1634,104 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) qbman_eq_desc_set_fq(&eqdesc, dpaa2_q->fqid); /*Clear the unused FD fields before sending*/ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn(*bufs)) { - uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; - - flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | - dqrr_index; - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); - *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; - } +tx_again: + /*Check if the queue is congested*/ + retry_count = 0; + while (qbman_result_SCN_state(dpaa2_q->cscn)) { + retry_count++; + /* Retry for some time before giving up */ + if (retry_count > CONG_RETRY_COUNT) + goto skip_tx; + } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], mempool_to_bpid(mp)); -#ifdef RTE_LIBRTE_MEMPOOL_DEBUG - rte_mempool_check_cookies - (rte_mempool_from_obj((void *)*bufs), - (void **)bufs, 1, 0); -#endif - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? + dpaa2_eqcr_size : nb_pkts; - if (unlikely(RTE_MBUF_HAS_EXTBUF(*bufs))) { - if (unlikely((*bufs)->nb_segs > 1)) { - mp = (*bufs)->pool; - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - mempool_to_bpid(mp))) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, 0); - } - bufs++; -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif - continue; - } + for (loop = 0; loop < frames_to_send; loop++) { + dy_conf[loop] = false; + if (*dpaa2_seqn(*bufs)) { + uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; + + flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; + DPAA2_PER_LCORE_DQRR_SIZE--; + DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); + *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; + } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); + if (unlikely((*bufs)->ol_flags + & RTE_MBUF_F_TX_VLAN)) { + ret = rte_vlan_insert(bufs); + if (ret) goto send_n_return; - } + } - if (unlikely((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN)) { - int ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR("S/G support not added" - " for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } -#ifdef RTE_LIBRTE_IEEE1588 - enable_tx_tstamp(&fd_arr[loop]); -#endif + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { bufs++; + continue; } - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], &flags[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop]); + } else { + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, priv->tx_conf_type, &dy_conf[loop]); } - - num_tx += loop; - nb_pkts -= loop; + if (ret) + goto send_n_return; + bufs++; } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); + loop = 0; + retry_count = 0; + while (loop < frames_to_send) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, + &fd_arr[loop], &flags[loop], + frames_to_send - loop); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { + num_tx += loop; + nb_pkts -= loop; + goto send_n_return; + } + } else { + loop += ret; + retry_count = 0; + } } + num_tx += loop; + nb_pkts -= loop; + if (nb_pkts > 0) + goto tx_again; + + dpaa2_q->tx_pkts += num_tx; + return num_tx; send_n_return: /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[i], - &flags[i], - loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } + retry_count = 0; + i = 0; + while (i < loop) { + ret = qbman_swp_enqueue_multiple(swp, &eqdesc, &fd_arr[i], + &flags[i], loop - i); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + break; + } else { + i += ret; + retry_count = 0; } - num_tx += i; - } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); } + num_tx += i; - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; +skip_tx: dpaa2_q->tx_pkts += num_tx; return num_tx; @@ -1772,149 +1806,108 @@ dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_tx_multi_txq_ordered) uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, - struct rte_mbuf **bufs, uint16_t nb_pkts) + struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to multiple queues respectively.*/ - uint32_t loop, i, retry_count; - int32_t ret; + uint32_t loop, retry_count, sent = 0; + int32_t ret = 0; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; - struct rte_mempool *mp; + struct rte_mempool *hw_mp; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; struct dpaa2_queue *dpaa2_q[MAX_TX_RING_SLOTS]; struct qbman_swp *swp; - uint16_t bpid; - struct rte_mbuf *mi; struct rte_eth_dev_data *eth_data; struct dpaa2_dev_priv *priv; struct dpaa2_queue *order_sendq; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; + uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", + DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } } swp = DPAA2_PER_LCORE_PORTAL; +tx_again: frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - dpaa2_q[loop] = (struct dpaa2_queue *)queue[loop]; + dpaa2_q[loop] = queue[loop]; + if (dpaa2_q[loop]->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q[loop], false); eth_data = dpaa2_q[loop]->eth_data; priv = eth_data->dev_private; - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { + dy_conf[loop] = false; + if (unlikely(!priv->bp_list)) { + DPAA2_PMD_ERR("%s's buffer pool not initialized!", + eth_data->name); + ret = -ENOMEM; + goto send_frames; + } + hw_mp = priv->bp_list->mp; + if (!priv->en_loose_ordered && + (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP)) { + if (!num_free_eq_desc) { + num_free_eq_desc = dpaa2_free_eq_descriptors(); if (!num_free_eq_desc) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (!num_free_eq_desc) - goto send_frames; + ret = -EIO; + goto send_frames; } - num_free_eq_desc--; } + num_free_eq_desc--; } DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q[loop]->fqid); + eth_data, dpaa2_q[loop]->fqid); /* Check if the queue is congested */ retry_count = 0; while (qbman_result_SCN_state(dpaa2_q[loop]->cscn)) { retry_count++; /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) + if (retry_count > CONG_RETRY_COUNT) { + ret = -ETIME; goto send_frames; + } } /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); if (*dpaa2_seqn(*bufs) && priv->en_ordered) { - order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); + order_sendq = priv->tx_vq[0]; + dpaa2_set_enqueue_descriptor(order_sendq, *bufs, + &eqdesc[loop]); } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q[loop]->fqid); + qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); + qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); } - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_frames; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_frames; + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, + *bufs, &fd_arr[loop], priv->tx_conf_type); + if (likely(!ret)) { + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; + bufs++; + continue; } - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_frames; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_frames; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); + if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop]); } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_frames; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop]); } - + if (ret) + goto send_frames; + if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) + dy_conf[loop] = true; bufs++; } @@ -1935,237 +1928,26 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, break; } } + nb_pkts -= loop; + sent += loop; + if (nb_pkts > 0 && !ret) + goto tx_again; - for (i = 0; i < free_count; i++) { - if (buf_to_free[i].pkt_id < loop) - rte_pktmbuf_free_seg(buf_to_free[i].seg); - } - return loop; + return sent; } /* Callback to handle sending ordered packets through WRIOP based interface */ uint16_t -dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) +dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) { - /* Function to transmit the frames to given device and VQ*/ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_queue *order_sendq = (struct dpaa2_queue *)priv->tx_vq[0]; - struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - struct rte_mbuf *mi; - struct rte_mempool *mp; - struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; - struct qbman_swp *swp; - uint32_t frames_to_send, num_free_eq_desc; - uint32_t loop, retry_count; - int32_t ret; - uint16_t num_tx = 0; - uint16_t bpid; - struct sw_buf_free buf_to_free[DPAA2_MAX_SGS * dpaa2_dqrr_size]; - uint32_t free_count = 0; - - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); - if (ret) { - DPAA2_PMD_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); - return 0; - } - } - swp = DPAA2_PER_LCORE_PORTAL; - - DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q->fqid); - - /* This would also handle normal and atomic queues as any type - * of packet can be enqueued when ordered queues are being used. - */ - while (nb_pkts) { - /*Check if the queue is congested*/ - retry_count = 0; - while (qbman_result_SCN_state(dpaa2_q->cscn)) { - retry_count++; - /* Retry for some time before giving up */ - if (retry_count > CONG_RETRY_COUNT) { - if (dpaa2_q->tm_sw_td) - goto sw_td; - goto skip_tx; - } - } - - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; - - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (num_free_eq_desc < frames_to_send) - frames_to_send = num_free_eq_desc; - } - } - - for (loop = 0; loop < frames_to_send; loop++) { - /*Prepare enqueue descriptor*/ - qbman_eq_desc_clear(&eqdesc[loop]); - - if (*dpaa2_seqn(*bufs)) { - /* Use only queue 0 for Tx in case of atomic/ - * ordered packets as packets can get unordered - * when being transmitted out from the interface - */ - dpaa2_set_enqueue_descriptor(order_sendq, - (*bufs), - &eqdesc[loop]); - } else { - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_fq(&eqdesc[loop], - dpaa2_q->fqid); - } - - if (likely(RTE_MBUF_DIRECT(*bufs))) { - mp = (*bufs)->pool; - /* Check the basic scenario and set - * the FD appropriately here itself. - */ - if (likely(mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - (*bufs)->nb_segs == 1 && - rte_mbuf_refcnt_read((*bufs)) == 1)) { - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { - ret = rte_vlan_insert(bufs); - if (ret) - goto send_n_return; - } - DPAA2_MBUF_TO_CONTIG_FD((*bufs), - &fd_arr[loop], - mempool_to_bpid(mp)); - bufs++; - continue; - } - } else { - mi = rte_mbuf_from_indirect(*bufs); - mp = mi->pool; - } - /* Not a hw_pkt pool allocated frame */ - if (unlikely(!mp || !priv->bp_list)) { - DPAA2_PMD_ERR("Err: No buffer pool attached"); - goto send_n_return; - } + uint16_t i; + void *mq[nb_pkts]; - if (mp->ops_index != priv->bp_list->dpaa2_ops_index) { - DPAA2_PMD_WARN("Non DPAA2 buffer pool"); - /* alloc should be from the default buffer pool - * attached to this interface - */ - bpid = priv->bp_list->buf_pool.bpid; - - if (unlikely((*bufs)->nb_segs > 1)) { - DPAA2_PMD_ERR( - "S/G not supp for non hw offload buffer"); - goto send_n_return; - } - if (eth_copy_mbuf_to_fd(*bufs, - &fd_arr[loop], bpid)) { - goto send_n_return; - } - /* free the original packet */ - rte_pktmbuf_free(*bufs); - } else { - bpid = mempool_to_bpid(mp); - if (unlikely((*bufs)->nb_segs > 1)) { - if (eth_mbuf_to_sg_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, - bpid)) - goto send_n_return; - } else { - eth_mbuf_to_fd(*bufs, - &fd_arr[loop], - buf_to_free, - &free_count, - loop, bpid); - } - } - bufs++; - } + for (i = 0; i < nb_pkts; i++) + mq[i] = queue; - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[loop], &fd_arr[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } - } else { - loop += ret; - retry_count = 0; - } - } - - num_tx += loop; - nb_pkts -= loop; - } - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; - -send_n_return: - /* send any already prepared fd */ - if (loop) { - unsigned int i = 0; - - retry_count = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[i], &fd_arr[i], loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } - } - num_tx += i; - } -skip_tx: - dpaa2_q->tx_pkts += num_tx; - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - return num_tx; -sw_td: - for (loop = 0; loop < free_count; loop++) { - if (buf_to_free[loop].pkt_id < num_tx) - rte_pktmbuf_free_seg(buf_to_free[loop].seg); - } - - /* free the pending buffers */ - rte_pktmbuf_free_bulk(bufs, nb_pkts); - - num_tx += nb_pkts; - dpaa2_q->tx_pkts += num_tx; - - return num_tx; + return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); } /* This function loopbacks all the received packets.*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 13/65] net/dpaa2: support runtime IEEE1588 timestamping 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (11 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 12/65] The dpaa2 PMD so far supported only two Tx buffer release schemes: direct release by hardware, and an absolute Tx confirmation mode (drv_tx_conf=1) where every transmitted buffer is returned on a Tx confirmation queue that software must poll to free the buffers. Absolute confirmation adds a confirmation descriptor and a poll cost for all packets, even those the hardware could free on its own Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 14/65] bus/fslmc: consume dpaa2 DQRR entries in batches Prashant Gupta ` (51 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> IEEE1588 timestamping in the dpaa2 PMD was only available when the whole DPDK build was compiled with RTE_LIBRTE_IEEE1588. The timesync ops, the Tx confirmation timestamp read and the one-step PTP setup were all guarded by that build-time macro, and the Rx timestamp relied on the global dpaa2_enable_ts[] / dpaa2_timestamp_dynfield_offset state. This made PTP a compile-time decision shared by all ports and prevented enabling it per device at runtime. Rework the timestamping path to be controlled at runtime: - Drop the RTE_LIBRTE_IEEE1588 guards around the timesync ops and the dprtc object registration, and remove the global dpaa2_enable_ts[], dpaa2_timestamp_rx_dynflag and dpaa2_timestamp_dynfield_offset variables. Rx/Tx timestamping is now tracked per device through priv->flags (DPAA2_IEEE1588_RX_TS_FLAG / DPAA2_IEEE1588_TX_TS_FLAG) and the per-device rx_ts_offset / rx_ts_flag dynfield registration. - Enable Tx one-step PTP at timesync_enable() time and update the correction offset at runtime from the actual PTP header of each transmitted frame (dpaa2_dev_tx_ptp_one_step_runtime), using the shared dpaax_ptp helpers to parse the header. The Tx path marks timestamp requests, forces dynamic confirmation for those frames, and the Tx confirmation handler records the egress timestamp. - Make the shared PTP state SMP-safe by converting rx_timestamp, tx_timestamp, next_txq_to_cnf and the per-queue ts_to_cnfd pending counter to C11 atomics, and read the Tx timestamp by draining the confirmation queue until the pending count reaches zero. - Add an optional debug trace (DPAA2_IEEE1588_DEBUG_FLAG, enabled when the PMD log level is DEBUG) for the timesync operations. Since one-step PTP is now configured internally, remove the experimental APIs rte_pmd_dpaa2_set_one_step_ts() and rte_pmd_dpaa2_get_one_step_ts() and document their removal in the 26.11 release notes. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 2 + drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/net/dpaa2/dpaa2_ethdev.c | 89 +---------- drivers/net/dpaa2/dpaa2_ethdev.h | 38 ++++- drivers/net/dpaa2/dpaa2_ptp.c | 175 ++++++++++++++++++---- drivers/net/dpaa2/dpaa2_rxtx.c | 190 +++++++++++++++++++----- drivers/net/dpaa2/rte_pmd_dpaa2.h | 10 -- 7 files changed, 335 insertions(+), 170 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 9835d74b17..70266464d2 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -163,6 +163,8 @@ Removed Items This section is a comment. Do not overwrite or remove it. Also, make sure to start the actual text at the margin. ======================================================= +* net/dpaa2: Removed the experimental one-step PTP APIs + ``rte_pmd_dpaa2_set_one_step_ts()`` and ``rte_pmd_dpaa2_get_one_step_ts()``. * Removed deprecated symbols: diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 48a465c206..9dba5dbbd1 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -199,6 +199,7 @@ struct __rte_cache_aligned dpaa2_queue { uint16_t tm_sw_td; /*!< TM software taildrop */ uint64_t offloads; uint64_t lpbk_cntx; + RTE_ATOMIC(int32_t) ts_to_cnfd; uint8_t data_stashing_off; /* NAPI rx-interrupt: per-queue DPCON bound to this FQ at dev_start * (DEST_DPCON, static); the polling worker points the channel's CDAN at diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f4ed12f45a..f2ba6d2c7c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -135,11 +135,6 @@ static uint64_t dev_tx_offloads_sup = /* Tx offloads which cannot be disabled */ static uint64_t dev_tx_offloads_nodis = RTE_ETH_TX_OFFLOAD_MULTI_SEGS; -/* enable timestamp in mbuf */ -bool dpaa2_enable_ts[RTE_MAX_ETHPORTS]; -uint64_t dpaa2_timestamp_rx_dynflag; -int dpaa2_timestamp_dynfield_offset = -1; - /* Rx descriptor limit when DPNI loads PFDRs in PEB */ #define MAX_NB_RX_DESC_IN_PEB 11264 static int total_nb_rx_desc; @@ -791,9 +786,6 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) int tx_l4_csum_offload = false; int ret, tc_index; uint32_t max_rx_pktlen; -#if defined(RTE_LIBRTE_IEEE1588) - uint16_t ptp_correction_offset; -#endif PMD_INIT_FUNC_TRACE(); @@ -875,25 +867,15 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) return ret; } -#if !defined(RTE_LIBRTE_IEEE1588) - if (rx_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) -#endif - { - ret = rte_mbuf_dyn_rx_timestamp_register( - &dpaa2_timestamp_dynfield_offset, - &dpaa2_timestamp_rx_dynflag); - if (ret != 0) { + if (rx_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) { + ret = rte_mbuf_dyn_rx_timestamp_register(&priv->rx_ts_offset, + &priv->rx_ts_flag); + if (ret) { DPAA2_PMD_ERR("Error to register timestamp field/flag"); - return -rte_errno; + return ret; } - dpaa2_enable_ts[dev->data->port_id] = true; } -#if defined(RTE_LIBRTE_IEEE1588) - /* By default setting ptp correction offset for Ethernet SYNC packets */ - ptp_correction_offset = RTE_ETHER_HDR_LEN + 8; - rte_pmd_dpaa2_set_one_step_ts(dev->data->port_id, ptp_correction_offset, 0); -#endif if (tx_offloads & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) tx_l3_csum_offload = true; @@ -3377,7 +3359,6 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, -#if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, .timesync_read_time = dpaa2_timesync_read_time, @@ -3385,7 +3366,6 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .timesync_adjust_time = dpaa2_timesync_adjust_time, .timesync_read_rx_timestamp = dpaa2_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = dpaa2_timesync_read_tx_timestamp, -#endif }; /* Populate the mac address from physically available (u-boot/firmware) and/or @@ -3596,10 +3576,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->options = attr.options; priv->max_mac_filters = attr.mac_filter_entries; priv->max_vlan_filters = attr.vlan_filter_entries; -#if defined(RTE_LIBRTE_IEEE1588) - DPAA2_PMD_INFO("DPDK IEEE1588 is enabled"); - priv->flags |= DPAA2_TX_CONF_ENABLE; -#endif /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); @@ -3763,61 +3739,6 @@ rte_pmd_dpaa2_ep_name(uint32_t eth_id) return priv->ep_name; } -#if defined(RTE_LIBRTE_IEEE1588) -RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_get_one_step_ts, 24.11) -int -rte_pmd_dpaa2_get_one_step_ts(uint16_t port_id, bool mc_query) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = priv->eth_dev->process_private; - struct dpni_single_step_cfg ptp_cfg; - int err; - - if (!mc_query) - return priv->ptp_correction_offset; - - err = dpni_get_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &ptp_cfg); - if (err) { - DPAA2_PMD_ERR("Failed to retrieve onestep configuration"); - return err; - } - - if (!ptp_cfg.ptp_onestep_reg_base) { - DPAA2_PMD_ERR("1588 onestep reg not available"); - return -1; - } - - priv->ptp_correction_offset = ptp_cfg.offset; - - return priv->ptp_correction_offset; -} - -RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_set_one_step_ts, 24.11) -int -rte_pmd_dpaa2_set_one_step_ts(uint16_t port_id, uint16_t offset, uint8_t ch_update) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - struct dpni_single_step_cfg cfg; - int err; - - cfg.en = 1; - cfg.ch_update = ch_update; - cfg.offset = offset; - cfg.peer_delay = 0; - - err = dpni_set_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (err) - return err; - - priv->ptp_correction_offset = offset; - - return 0; -} -#endif - static int dpaa2_tx_sg_pool_init(void) { char name[RTE_MEMZONE_NAMESIZE]; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 28d6eb04ac..ddc205c2d4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -8,6 +8,7 @@ #ifndef _DPAA2_ETHDEV_H #define _DPAA2_ETHDEV_H +#include <rte_time.h> #include <rte_compat.h> #include <rte_event_eth_rx_adapter.h> #include <rte_pmd_dpaa2.h> @@ -102,6 +103,12 @@ #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(10) +#define DPAA2_IEEE1588_DEBUG_FLAG RTE_BIT32(11) + +#define DPAA2_IEEE1588_TX_TS_FLAG RTE_BIT32(12) + +#define DPAA2_IEEE1588_RX_TS_FLAG RTE_BIT32(13) + /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -220,11 +227,6 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; @@ -482,14 +484,16 @@ struct dpaa2_dev_priv { uint64_t ss_iova; uint64_t ss_param_iova; /*stores timestamp of last received packet on dev*/ - uint64_t rx_timestamp; + RTE_ATOMIC(uint64_t) rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ - uint64_t tx_timestamp; + RTE_ATOMIC(uint64_t) tx_timestamp; + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores next tx queue to be confirmed that should be processed, * it corresponds to last packet transmitted */ - struct dpaa2_queue *next_txq_to_cnf; + RTE_ATOMIC(struct dpaa2_queue *) next_txq_to_cnf; struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; @@ -560,6 +564,21 @@ dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, } } +static inline void +dpaa2_timestamp_debug(struct dpaa2_dev_priv *priv, + const char *prefix, uint64_t timestamp) +{ + struct timespec ts; + + if (likely(!(priv->flags & DPAA2_IEEE1588_DEBUG_FLAG))) + return; + + ts = rte_ns_to_timespec(timestamp); + dpaa2_dump_print("DPAA2 TS DBG: %s: ns(%" PRIu64 ")->%" PRId64 + " seconds/%" PRId64 " nanoseconds", + prefix, timestamp, (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec); +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); @@ -622,6 +641,9 @@ void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); uint16_t dpaa2_dev_tx_conf(void *txq, int drain); +void +dpaa2_dev_tx_ptp_one_step_runtime(struct rte_eth_dev *dev, + struct rte_mbuf *buf, int *tstamp, int *set); int dpaa2_timesync_enable(struct rte_eth_dev *dev); int dpaa2_timesync_disable(struct rte_eth_dev *dev); int dpaa2_timesync_read_time(struct rte_eth_dev *dev, diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index 2863cad4dd..00f6d04c92 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -22,6 +22,7 @@ #include <dpaa2_ethdev.h> #include <dpaa2_pmd_logs.h> +#include <dpaax_ptp.h> struct dpaa2_dprtc_dev { struct fsl_mc_io dprtc; /** handle to DPRTC portal object */ @@ -30,52 +31,144 @@ struct dpaa2_dprtc_dev { }; static struct dpaa2_dprtc_dev *dprtc_dev; -int dpaa2_timesync_enable(struct rte_eth_dev *dev __rte_unused) +static int +dpaa2_timesync_set_one_step(struct rte_eth_dev *dev, + uint16_t offset, int udp) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = dev->process_private; + struct dpni_single_step_cfg cfg; + int err; + + memset(&cfg, 0, sizeof(struct dpni_single_step_cfg)); + cfg.en = 1; + cfg.ch_update = udp; + cfg.offset = offset; + cfg.peer_delay = 0; + + err = dpni_set_single_step_cfg(dpni, CMD_PRI_LOW, priv->token, &cfg); + if (err) + return err; + + priv->ptp_correction_offset = offset; + + return 0; +} + +void +dpaa2_dev_tx_ptp_one_step_runtime(struct rte_eth_dev *dev, + struct rte_mbuf *buf, int *tstamp, int *set) { + uint16_t ts_offset; + int is_udp = false, ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (tstamp) + *tstamp = false; + if (set) + *set = false; + + if (!dpaax_timesync_ptp_parse_header(buf, + &ts_offset, &is_udp)) { + DPAA2_PMD_WARN("Tx packet is not PTP frame."); + ret = -EINVAL; + } else { + if (ts_offset != priv->ptp_correction_offset) { + ret = dpaa2_timesync_set_one_step(dev, ts_offset, is_udp); + if (ret) { + DPAA2_PMD_WARN("Change one step failed(%d)", ret); + } else { + DPAA2_PMD_INFO("Change one step from offset %d to %d", + priv->ptp_correction_offset, ts_offset); + priv->ptp_correction_offset = ts_offset; + if (set) + *set = true; + } + } + } + + if (!ret && tstamp) + *tstamp = true; +} + +int dpaa2_timesync_enable(struct rte_eth_dev *dev) +{ + uint16_t default_offset; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret; + + default_offset = RTE_ETHER_HDR_LEN + + offsetof(struct rte_dpaax_ptp_header, correction); + + ret = dpaa2_timesync_set_one_step(dev, default_offset, false); + if (ret) { + DPAA2_PMD_ERR("%s one step timesyc set failed(%d)", + dev->data->name, ret); + } else { + priv->flags |= DPAA2_IEEE1588_TX_TS_FLAG; + } + priv->flags |= DPAA2_IEEE1588_RX_TS_FLAG; + if (priv->tx_conf_type == DPAA2_TX_NO_CONF) { + DPAA2_PMD_WARN("%s Unable to read TX timestamp", + dev->data->name); + } + if (rte_log_get_level(dpaa2_logtype_pmd) == RTE_LOG_DEBUG) + priv->flags |= DPAA2_IEEE1588_DEBUG_FLAG; + return 0; } -int dpaa2_timesync_disable(struct rte_eth_dev *dev __rte_unused) +int dpaa2_timesync_disable(struct rte_eth_dev *dev) { + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + priv->ptp_correction_offset = 0; + priv->flags &= ~DPAA2_IEEE1588_RX_TS_FLAG; + priv->flags &= ~DPAA2_IEEE1588_TX_TS_FLAG; return 0; } int dpaa2_timesync_read_time(struct rte_eth_dev *dev, - struct timespec *timestamp) + struct timespec *timestamp) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ret = dprtc_get_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &ns); + dprtc_dev->token, &ns); if (ret) { DPAA2_PMD_ERR("dprtc_get_time failed ret: %d", ret); return ret; } *timestamp = rte_ns_to_timespec(ns); + dpaa2_timestamp_debug(priv, __func__, ns); return 0; } int dpaa2_timesync_write_time(struct rte_eth_dev *dev, - const struct timespec *ts) + const struct timespec *ts) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ns = rte_timespec_to_ns(ts); - ret = dprtc_set_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, ns); + dprtc_dev->token, ns); if (ret) { DPAA2_PMD_ERR("dprtc_set_time failed ret: %d", ret); return ret; } + dpaa2_timestamp_debug(priv, __func__, ns); return 0; } @@ -84,11 +177,13 @@ int dpaa2_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) { uint64_t ns; int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - RTE_SET_USED(dev); + if (!dprtc_dev) + return -ENODEV; ret = dprtc_get_time(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &ns); + dprtc_dev->token, &ns); if (ret) { DPAA2_PMD_ERR("dprtc_get_time failed ret: %d", ret); return ret; @@ -102,64 +197,85 @@ int dpaa2_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) DPAA2_PMD_ERR("dprtc_set_time failed ret: %d", ret); return ret; } + dpaa2_timestamp_debug(priv, "adjust delata", delta); + dpaa2_timestamp_debug(priv, "adjust absolute", ns); return 0; } int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, - struct timespec *timestamp) + struct timespec *timestamp) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - - if (priv->next_txq_to_cnf) { - while (!priv->tx_timestamp) - dpaa2_dev_tx_conf(priv->next_txq_to_cnf, false); - } else { - return -1; + struct dpaa2_queue *txq; + uint64_t ts; + + if (!(priv->flags & DPAA2_IEEE1588_TX_TS_FLAG) || + priv->tx_conf_type == DPAA2_TX_NO_CONF) + return -EINVAL; + + txq = rte_atomic_load_explicit(&priv->next_txq_to_cnf, + rte_memory_order_relaxed); + while (txq && rte_atomic_load_explicit(&txq->ts_to_cnfd, + rte_memory_order_relaxed) > 0) { + dpaa2_dev_tx_conf(txq, false); + txq = rte_atomic_load_explicit(&priv->next_txq_to_cnf, + rte_memory_order_relaxed); } - *timestamp = rte_ns_to_timespec(priv->tx_timestamp); + + ts = rte_atomic_load_explicit(&priv->tx_timestamp, + rte_memory_order_relaxed); + *timestamp = rte_ns_to_timespec(ts); + dpaa2_timestamp_debug(priv, __func__, ts); return 0; } int dpaa2_timesync_read_rx_timestamp(struct rte_eth_dev *dev, - struct timespec *timestamp, - uint32_t flags __rte_unused) + struct timespec *timestamp, uint32_t flags __rte_unused) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - *timestamp = rte_ns_to_timespec(priv->rx_timestamp); + uint64_t ts; + + if (!(priv->flags & DPAA2_IEEE1588_RX_TS_FLAG)) + return -EINVAL; + + ts = rte_atomic_load_explicit(&priv->rx_timestamp, + rte_memory_order_relaxed); + *timestamp = rte_ns_to_timespec(ts); + dpaa2_timestamp_debug(priv, __func__, ts); + return 0; } -#if defined(RTE_LIBRTE_IEEE1588) static int dpaa2_create_dprtc_device(int vdev_fd __rte_unused, struct vfio_device_info *obj_info __rte_unused, struct rte_dpaa2_device *obj) { struct dprtc_attr attr; - int ret, dprtc_id = obj->object_id; + int ret = 0, dprtc_id = obj->object_id; PMD_INIT_FUNC_TRACE(); /* Allocate DPAA2 dprtc handle */ - dprtc_dev = rte_malloc(NULL, sizeof(struct dpaa2_dprtc_dev), 0); + dprtc_dev = rte_zmalloc(NULL, sizeof(struct dpaa2_dprtc_dev), 0); if (!dprtc_dev) { DPAA2_PMD_ERR("Memory allocation failed for DPRTC Device"); - return -1; + return -ENOMEM; } /* Open the dprtc object */ dprtc_dev->dprtc.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); ret = dprtc_open(&dprtc_dev->dprtc, CMD_PRI_LOW, dprtc_id, - &dprtc_dev->token); + &dprtc_dev->token); if (ret) { DPAA2_PMD_ERR("Unable to open dprtc object: err(%d)", ret); goto init_err; } ret = dprtc_get_attributes(&dprtc_dev->dprtc, CMD_PRI_LOW, - dprtc_dev->token, &attr); + dprtc_dev->token, &attr); if (ret) { DPAA2_PMD_ERR("Unable to get dprtc attr: err(%d)", ret); goto init_err; @@ -172,7 +288,7 @@ dpaa2_create_dprtc_device(int vdev_fd __rte_unused, init_err: rte_free(dprtc_dev); - return -1; + return ret; } static struct rte_dpaa2_object rte_dpaa2_dprtc_obj = { @@ -181,4 +297,3 @@ static struct rte_dpaa2_object rte_dpaa2_dprtc_obj = { }; RTE_PMD_REGISTER_DPAA2_OBJECT(dprtc, rte_dpaa2_dprtc_obj); -#endif diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 24631b16c5..3e8fc29baa 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -22,6 +22,7 @@ #include <dpaa2_hw_pvt.h> #include <dpaa2_hw_dpio.h> #include <dpaa2_hw_mempool.h> +#include <dpaax_ptp.h> #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" @@ -39,13 +40,6 @@ #define DPAA2_FAST_PATH_PTYPE_ETH_IPV6_TCP \ (DPAA2_FAST_PATH_PTYPE_ETH_IPV6 | RTE_PTYPE_L4_TCP) -static inline rte_mbuf_timestamp_t * -dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) -{ - return RTE_MBUF_DYNFIELD(mbuf, - dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); -} - static inline void dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) { @@ -171,6 +165,28 @@ dpaa2_dev_rx_mbuf_flc_offload(struct rte_mbuf *m, } } +static inline void +dpaa2_dev_rx_read_timestamp(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m) +{ + struct dpaa2_annot_hdr *annotation; + rte_mbuf_timestamp_t *ts; + + if (!(priv->flags & DPAA2_IEEE1588_RX_TS_FLAG)) + return; + + annotation = (void *)((uint8_t *)m->buf_addr + DPAA2_FD_PTA_SIZE); + if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_PTP)) { + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_TMST; + } + ts = RTE_MBUF_DYNFIELD(m, priv->rx_ts_offset, void *); + *ts = annotation->word2; + m->ol_flags |= priv->rx_ts_flag; + rte_atomic_store_explicit(&priv->rx_timestamp, *ts, rte_memory_order_relaxed); + dpaa2_timestamp_debug(priv, __func__, priv->rx_timestamp); +} + static inline void __rte_hot dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, struct rte_mbuf *m, const struct qbman_fd *fd, @@ -243,13 +259,6 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, if (unlikely(is_vlan && !default_parsed)) dpaa2_dev_rx_parse_vlan(m, &m->packet_type, frc_parse, annotation); - if (dpaa2_enable_ts[m->port]) { - *dpaa2_timestamp_dynfield(m) = annotation->word2; - m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); - } - DPAA2_PMD_DP_DEBUG("HW frc = 0x%x packet type = 0x%x ol_flags = 0x%lx", frc_u.u16, m->packet_type, m->ol_flags); } @@ -369,13 +378,6 @@ dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - if (dpaa2_enable_ts[mbuf->port]) { - *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; - mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(mbuf)); - } - /* Check detailed parsing requirement */ if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); @@ -532,6 +534,27 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return mbuf; } +static void dpaa2_dev_tx_enable_tstamp(struct qbman_fd *fd) +{ + struct dpaa2_faead *fd_faead; + void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + + /* Set frame annotation status field as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FASV; + + /* Set frame annotation egress action descriptor as valid */ + (fd)->simple.frc |= DPAA2_FD_FRC_FAEADV; + + /* Set Annotation Length as 128B */ + (fd)->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + + /* enable update of confirmation frame annotation */ + fd_faead = (void *)((size_t)fd_va + + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD); +} + static inline struct rte_mbuf * dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) { @@ -554,18 +577,31 @@ dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) static inline void dpaa2_dev_tx_config_dynamic_confirm(struct qbman_fd *fd, - struct dpaa2_queue *txq, int enable) + struct dpaa2_queue *txq, int enable, int tstamp) { struct dpaa2_faead *fd_faead; void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); - DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | DPAA2_FD_FRC_FAEADV); + if (tstamp) { + DPAA2_SET_FD_FRC(fd, + DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV | DPAA2_FD_FRC_FASV); + fd->simple.ctrl |= DPAA2_FD_CTRL_ASAL; + } else { + DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | + DPAA2_FD_FRC_FAEADV); + } /* enable update of confirmation frame annotation */ fd_faead = (void *)((size_t)fd_va + DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); if (enable) { fd_faead->fqid = txq->tx_conf_queue->fqid; fd_faead->ctrl = DPAA2_TX_CONFIRM_ENABLE; + if (tstamp) { + fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | + DPAA2_ANNOT_FAEAD_UPDV | + DPAA2_ANNOT_FAEAD_UPD); + } } else { fd_faead->fqid = 0; fd_faead->ctrl &= (~DPAA2_TX_CONFIRM_ENABLE); @@ -682,7 +718,7 @@ static int __rte_noinline __rte_hot dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, struct rte_mbuf *mbuf, struct qbman_fd *fd, struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, - uint8_t *dy_conf) + uint8_t *dy_conf, int tstamp) { struct rte_mbuf *cur_seg = mbuf, *sg_mbuf; struct qbman_sge *sgt; @@ -695,7 +731,7 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, while (cur_seg) { if (!RTE_MBUF_DIRECT(cur_seg) || cur_seg->pool->ops_index != hw_mp->ops_index || - rte_mbuf_refcnt_read(cur_seg) > 1) { + rte_mbuf_refcnt_read(cur_seg) > 1 || tstamp) { need_dyconf = true; break; } @@ -706,7 +742,7 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, if (need_dyconf || conf == DPAA2_TX_ABSOLUTE_CONF) need_conf = true; - if (need_dyconf) + if (need_dyconf || tstamp) offset = DPAA2_FD_PTA_SIZE + DPAA2_DYN_TX_MIN_FD_OFFSET; if (mbuf->pool->ops_index == hw_mp->ops_index && @@ -769,7 +805,9 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, else DPAA2_RESET_FD_FLC(fd); if (need_dyconf) - dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true); + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); + else if (tstamp) + dpaa2_dev_tx_enable_tstamp(fd); if (cur_seg != sg_mbuf && need_conf) sg_mbuf->next = cur_seg; @@ -809,7 +847,7 @@ static int __rte_noinline __rte_hot dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, struct rte_mbuf *mbuf, struct qbman_fd *fd, struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, - uint8_t *dy_conf) + uint8_t *dy_conf, int tstamp) { int need_dyconf = false, need_conf = false; struct rte_mbuf *mi; @@ -829,7 +867,7 @@ dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, if (conf == DPAA2_TX_DYNAMIC_CONF && (mbuf->pool->ops_index != hw_mp->ops_index || RTE_MBUF_HAS_EXTBUF(mbuf) || - rte_mbuf_refcnt_read(mbuf) > 1)) + rte_mbuf_refcnt_read(mbuf) > 1 || tstamp)) need_dyconf = true; if (conf == DPAA2_TX_ABSOLUTE_CONF || need_dyconf) need_conf = true; @@ -847,9 +885,11 @@ dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, } if (need_dyconf) { - dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true); + dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); if (dy_conf) *dy_conf = true; + } else if (tstamp) { + dpaa2_dev_tx_enable_tstamp(fd); } return ret; @@ -935,6 +975,8 @@ dpaa2_dev_rx_err_pkts_dump(struct dpaa2_queue *dpaa2_q) if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) dpaa2_dev_rx_parse_offset(priv, mbuf, fd); + dpaa2_dev_rx_read_timestamp(priv, mbuf); + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -1105,6 +1147,8 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); + dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1356,6 +1400,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); + dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; @@ -1399,6 +1444,8 @@ dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, return true; } +#define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + uint16_t dpaa2_dev_tx_conf(void *txq, int drain) { /* Function receive frames for a given device and VQ*/ @@ -1416,7 +1463,10 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) struct rte_mbuf *mbufs[dpaa2_dqrr_size]; struct rte_mempool *mp = NULL; - #define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) + struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct dpaa2_annot_hdr *annotation; + void *v_addr; conf_again: bulk_free = true; @@ -1514,6 +1564,17 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) if (bulk_free && !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) bulk_free = false; + if (unlikely(mbufs[idx]->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)) { + v_addr = mbufs[idx]->buf_addr; + annotation = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); + rte_atomic_store_explicit(&priv->tx_timestamp, + annotation->word2, rte_memory_order_relaxed); + rte_atomic_store_explicit(&priv->next_txq_to_cnf, + dpaa2_txq, rte_memory_order_relaxed); + rte_atomic_fetch_sub_explicit(&dpaa2_q->ts_to_cnfd, 1, + rte_memory_order_relaxed); + dpaa2_timestamp_debug(priv, __func__, priv->tx_timestamp); + } idx++; dq_storage++; if (idx >= dpaa2_dqrr_size) @@ -1592,7 +1653,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ uint32_t loop, retry_count, i; - int32_t ret; + int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send; struct qbman_eq_desc eqdesc; @@ -1638,6 +1699,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) tx_again: /*Check if the queue is congested*/ retry_count = 0; + ptp_set_count = 0; while (qbman_result_SCN_state(dpaa2_q->cscn)) { retry_count++; /* Retry for some time before giving up */ @@ -1666,6 +1728,19 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) goto send_n_return; } + tstamp[loop] = false; + if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && + (priv->flags & DPAA2_IEEE1588_TX_TS_FLAG))) { + ptp_set = false; + dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, + &tstamp[loop], &ptp_set); + if (ptp_set) + ptp_set_count++; + if (ptp_set_count > 1) + DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); + goto skip_fast_mbuf2fd; + } + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, *bufs, &fd_arr[loop], priv->tx_conf_type); if (likely(!ret)) { @@ -1673,12 +1748,13 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) continue; } +skip_fast_mbuf2fd: if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q, priv->tx_conf_type, &dy_conf[loop]); + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } else { ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q, priv->tx_conf_type, &dy_conf[loop]); + dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } if (ret) goto send_n_return; @@ -1706,6 +1782,14 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) num_tx += loop; nb_pkts -= loop; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + for (i = 0; i < loop; i++) { + if (tstamp[i]) { + rte_atomic_fetch_add_explicit(&dpaa2_q->tx_conf_queue->ts_to_cnfd, + 1, rte_memory_order_relaxed); + } + } + } if (nb_pkts > 0) goto tx_again; @@ -1730,6 +1814,15 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } } num_tx += i; + if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { + loop = i; + for (i = 0; i < loop; i++) { + if (tstamp[i]) { + rte_atomic_fetch_add_explicit(&dpaa2_q->tx_conf_queue->ts_to_cnfd, + 1, rte_memory_order_relaxed); + } + } + } skip_tx: dpaa2_q->tx_pkts += num_tx; @@ -1809,8 +1902,8 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to multiple queues respectively.*/ - uint32_t loop, retry_count, sent = 0; - int32_t ret = 0; + uint32_t loop, retry_count, sent = 0, i; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; struct rte_mempool *hw_mp; @@ -1833,6 +1926,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, swp = DPAA2_PER_LCORE_PORTAL; tx_again: + ptp_set_count = 0; frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; @@ -1888,6 +1982,19 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); } + tstamp[loop] = false; + if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && + (priv->flags & DPAA2_IEEE1588_TX_TS_FLAG))) { + ptp_set = false; + dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, + &tstamp[loop], &ptp_set); + if (ptp_set) + ptp_set_count++; + if (ptp_set_count > 1) + DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); + goto skip_fast_mbuf2fd; + } + ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, *bufs, &fd_arr[loop], priv->tx_conf_type); if (likely(!ret)) { @@ -1897,12 +2004,13 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, continue; } +skip_fast_mbuf2fd: if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop]); + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } else { ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop]); + dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); } if (ret) goto send_frames; @@ -1930,6 +2038,12 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, } nb_pkts -= loop; sent += loop; + for (i = 0; i < loop; i++) { + if (tstamp[i] && dpaa2_q[i]->tx_conf_queue) { + rte_atomic_fetch_add_explicit(&dpaa2_q[i]->tx_conf_queue->ts_to_cnfd, + 1, rte_memory_order_relaxed); + } + } if (nb_pkts > 0 && !ret) goto tx_again; diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index 128adf3d1d..a6441eed65 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -148,14 +148,4 @@ __rte_experimental int rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off); - -#if defined(RTE_LIBRTE_IEEE1588) -__rte_experimental -int -rte_pmd_dpaa2_set_one_step_ts(uint16_t port_id, uint16_t offset, uint8_t ch_update); - -__rte_experimental -int -rte_pmd_dpaa2_get_one_step_ts(uint16_t port_id, bool mc_query); -#endif #endif /* _RTE_PMD_DPAA2_H */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 14/65] bus/fslmc: consume dpaa2 DQRR entries in batches 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (12 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 13/65] net/dpaa2: support runtime IEEE1588 timestamping Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 15/65] bus/fslmc: align dpaa2 event port depths with hardware rings Prashant Gupta ` (50 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Each DQRR entry consumed by the software portal costs a write to the cache-invalidate DCAP register. The DCAP register also supports a vector mode where a bitmap of DQRR indices is consumed with a single write, so accumulate the indices and flush the vector once half the ring is pending. A smaller threshold gives little benefit, and a threshold close to the ring size starves WRIOP of DQRR space. Because entries are now released in batches, a caller that stops polling a portal must flush the pending vector explicitly. Pass a NULL dequeue result to qbman_swp_dqrr_consume() to do that when the eventdev dequeue finds the portal dry, when the net PMD finishes draining a portal, and when a portal is released back to the bus. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 4 ++ .../fslmc/qbman/include/fsl_qbman_portal.h | 5 +- drivers/bus/fslmc/qbman/qbman_portal.c | 63 +++++++++++++++++-- drivers/bus/fslmc/qbman/qbman_portal.h | 11 +++- drivers/event/dpaa2/dpaa2_eventdev.c | 4 ++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 + 6 files changed, 81 insertions(+), 8 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index b1443f327a..8af8600935 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -305,6 +305,10 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) { if (dpio_dev) { + /* consume indices may still be pending in the portal's DQRR + * consume vector; flush them before the portal is released. + */ + qbman_swp_dqrr_consume(dpio_dev->sw_portal, NULL); /* rx-queue interrupts (net PMD) can arm a portal without the * event driver; tear it down unconditionally. Safe when never * armed: intr_deinit returns early if intr is not enabled. diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index b9e7789766..73e57bcdc1 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -451,7 +451,10 @@ void qbman_swp_prefetch_dqrr_next(struct qbman_swp *s); * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from * qbman_swp_dqrr_next(). * @s: the software portal object. - * @dq: the DQRR entry to be consumed. + * @dq: the DQRR entry to be consumed, NULL to consume the entries accumulated + * so far. Entries are accumulated and consumed in batches, so a caller which + * stops polling the portal must call this with a NULL dq to release the + * entries it has already processed. */ __rte_internal void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq); diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index 7b666d4ef9..28a9d87c3c 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020,2023-2024 NXP + * Copyright 2018-2020,2023-2024,2026 NXP * */ @@ -9,13 +9,20 @@ #include "qbman_portal.h" #include <eal_export.h> +#include <rte_bitops.h> /* QBMan portal management command codes */ #define QBMAN_MC_ACQUIRE 0x30 #define QBMAN_WQCHAN_CONFIGURE 0x46 /* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ -#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6) +#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) + +/* DCAP consume-index-vector mode: the vector of DQRR indices to consume starts + * at bit 16 of DCAP and bit 8 selects vector mode over single-index mode. + */ +#define DQRR_DCAP_CI_VEC_OFFSET 16 +#define DQRR_DCAP_CI_VEC_SELECT 0x100 /* QBMan FQ management command codes */ #define QBMAN_FQ_SCHEDULE 0x48 @@ -284,6 +291,13 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) p->dqrr.dqrr_size = 8; p->dqrr.reset_bug = 0; } + /* Consume DQRR entries in vector mode by default and flush the vector + * once half the ring is pending. A smaller threshold gives little + * benefit; a threshold close to the ring size starves WRIOP of DQRR + * space and slows its enqueues down. + */ + p->dqrr.ci_vec_en = p->dqrr.dqrr_size <= (32 - DQRR_DCAP_CI_VEC_OFFSET); + p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { @@ -2225,13 +2239,47 @@ const struct qbman_result *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s) return p; } -/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ +/* Write the pending consume vector to DCAP if it holds at least "threshold" + * indices, consuming all of them with a single register access. + */ +static inline void +qbman_swp_dqrr_vec_flush(struct qbman_swp *s, uint8_t threshold) +{ + if (s->dqrr.ci_count < threshold) + return; + + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + s->dqrr.ci_vector | DQRR_DCAP_CI_VEC_SELECT); + s->dqrr.ci_vector = 0; + s->dqrr.ci_count = 0; +} + +/* Add a DQRR index to the pending consume vector, flushing it once the + * configured threshold is reached. + */ +static inline void +qbman_swp_dqrr_vec_consume(struct qbman_swp *s, uint8_t idx) +{ + s->dqrr.ci_vector |= RTE_BIT32(idx + DQRR_DCAP_CI_VEC_OFFSET); + s->dqrr.ci_count++; + qbman_swp_dqrr_vec_flush(s, s->dqrr.ci_flush_th); +} + +/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). + * A NULL dq flushes any indices still pending in the consume vector, which + * the caller must do before it stops polling the portal. + */ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_consume) void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq) { - qbman_cinh_write(&s->sys, - QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); + if (unlikely(dq == NULL)) + qbman_swp_dqrr_vec_flush(s, 1); + else if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, QBMAN_IDX_FROM_DQRR(dq)); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, + QBMAN_IDX_FROM_DQRR(dq)); } /* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ @@ -2239,7 +2287,10 @@ RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_dqrr_idx_consume) void qbman_swp_dqrr_idx_consume(struct qbman_swp *s, uint8_t dqrr_index) { - qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); + if (s->dqrr.ci_vec_en) + qbman_swp_dqrr_vec_consume(s, dqrr_index); + else + qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index); } /*********************************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.h b/drivers/bus/fslmc/qbman/qbman_portal.h index 1cf7918309..db74db5fe1 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.h +++ b/drivers/bus/fslmc/qbman/qbman_portal.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2018-2020 NXP + * Copyright 2018-2020, 2026 NXP * */ @@ -93,6 +93,15 @@ struct qbman_swp { uint32_t valid_bit; uint8_t dqrr_size; int reset_bug; + /* Consume index vector: instead of writing DCAP once per + * consumed entry, the indices are accumulated in ci_vector + * and written with a single DCAP access once ci_count + * reaches ci_flush_th. + */ + bool ci_vec_en; + uint8_t ci_count; + uint8_t ci_flush_th; + uint32_t ci_vector; } dqrr; struct { uint32_t pi; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 95d9154b11..5d32bd9fd6 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -320,6 +320,10 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], do { dq = qbman_swp_dqrr_next(swp); if (!dq) { + /* portal is dry: consume whatever is still pending in + * the DQRR consume vector before leaving it idle. + */ + qbman_swp_dqrr_consume(swp, NULL); if (!num_pkts && timeout_ticks) { dpaa2_eventdev_dequeue_wait(timeout_ticks); timeout_ticks = 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f2ba6d2c7c..0fbc2c77b0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3083,6 +3083,8 @@ dpaa2_napi_drain_portal(struct dpaa2_dpio_dev *dpio) while ((dq = qbman_swp_dqrr_next(dpio->sw_portal))) qbman_swp_dqrr_consume(dpio->sw_portal, dq); + /* flush the indices still pending in the DQRR consume vector */ + qbman_swp_dqrr_consume(dpio->sw_portal, NULL); qbman_swp_interrupt_clear_status(dpio->sw_portal, 0xffffffff); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 15/65] bus/fslmc: align dpaa2 event port depths with hardware rings 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (13 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 14/65] bus/fslmc: consume dpaa2 DQRR entries in batches Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 16/65] net/dpaa2: support multi-DPNI FS redirect and QoS table v3 Prashant Gupta ` (49 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The event port dequeue and enqueue depths were fixed at 8. A dequeue drains the portal DQRR and an enqueue fills the EQCR, so the real limits are the sizes of those two rings, which differ per SoC and are known at run time. Report them instead, adding qbman_swp_portal_dqrr_size() to query the DQRR size (the EQCR size is already available as dpaa2_eqcr_size). The Tx adapter enqueue helpers sized their on-stack mbuf arrays from the advertised enqueue depth, which no longer bounds the burst the adapter may hand them, so bound the copy by the array itself and transmit in chunks. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- .../fslmc/qbman/include/fsl_qbman_portal.h | 7 ++ drivers/bus/fslmc/qbman/qbman_portal.c | 15 ++++ drivers/event/dpaa2/dpaa2_eventdev.c | 72 ++++++++++++------- drivers/event/dpaa2/dpaa2_eventdev.h | 4 +- 4 files changed, 69 insertions(+), 29 deletions(-) diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index 73e57bcdc1..fb1c6046ae 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -1222,6 +1222,13 @@ __rte_internal int qbman_swp_acquire(struct qbman_swp *s, uint16_t bpid, uint64_t *buffers, unsigned int num_buffers); +/** + * qbman_swp_portal_dqrr_size() - Number of entries in a portal's DQRR. + * @p: the software portal object, NULL to query the SoC's DQRR size. + */ +__rte_internal +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p); + /*****************/ /* FQ management */ /*****************/ diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index 28a9d87c3c..307c0e3d24 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -73,6 +73,11 @@ enum qbman_sdqcr_fc { static struct qbman_swp *portal_idx_map[MAX_QBMAN_PORTALS]; uint32_t qman_version; +/* DQRR size of the portals initialised so far. All portals of a SoC have the + * same size, so this doubles as the SoC's DQRR size for callers that have no + * portal at hand. + */ +static uint32_t dpaa2_portal_dqrr_size = 8; /* Internal Function declaration */ static int @@ -239,6 +244,15 @@ static int (*qbman_swp_release_ptr)(struct qbman_swp *s, const uint64_t *buffers, unsigned int num_buffers) = qbman_swp_release_direct; +RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_portal_dqrr_size) +uint32_t qbman_swp_portal_dqrr_size(struct qbman_swp *p) +{ + if (p != NULL) + return p->dqrr.dqrr_size; + + return dpaa2_portal_dqrr_size; +} + /*********************************/ /* Portal constructor/destructor */ /*********************************/ @@ -298,6 +312,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) */ p->dqrr.ci_vec_en = p->dqrr.dqrr_size <= (32 - DQRR_DCAP_CI_VEC_OFFSET); p->dqrr.ci_flush_th = p->dqrr.dqrr_size / 2; + dpaa2_portal_dqrr_size = p->dqrr.dqrr_size; ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); if (ret) { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 5d32bd9fd6..ddcf7b3678 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017,2019-2022 NXP + * Copyright 2017,2019-2022,2026 NXP */ #include <assert.h> @@ -389,10 +389,11 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, /* we only support dpio up to number of cores */ if (dev_info->max_event_ports > rte_lcore_count()) dev_info->max_event_ports = rte_lcore_count(); - dev_info->max_event_port_dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - dev_info->max_event_port_enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + /* A dequeue drains the portal DQRR and an enqueue fills the EQCR, so + * the hardware ring sizes are the real limits. + */ + dev_info->max_event_port_dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + dev_info->max_event_port_enqueue_depth = dpaa2_eqcr_size; dev_info->max_num_events = DPAA2_EVENT_MAX_NUM_EVENTS; dev_info->event_dev_cap = RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED | RTE_EVENT_DEV_CAP_ATOMIC | @@ -527,12 +528,9 @@ dpaa2_eventdev_port_def_conf(struct rte_eventdev *dev, uint8_t port_id, RTE_SET_USED(dev); RTE_SET_USED(port_id); - port_conf->new_event_threshold = - DPAA2_EVENT_MAX_NUM_EVENTS; - port_conf->dequeue_depth = - DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH; - port_conf->enqueue_depth = - DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH; + port_conf->new_event_threshold = DPAA2_EVENT_MAX_NUM_EVENTS; + port_conf->dequeue_depth = qbman_swp_portal_dqrr_size(NULL); + port_conf->enqueue_depth = dpaa2_eqcr_size; port_conf->event_port_cfg = 0; } @@ -977,18 +975,31 @@ dpaa2_eventdev_txa_enqueue_same_dest(void *port, struct rte_event ev[], uint16_t nb_events) { - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH], *m0; - uint8_t qid, i; + struct rte_mbuf *m[MAX_TX_RING_SLOTS], *m0; + uint16_t sent = 0, burst, i, port_id; + uint8_t qid; RTE_SET_USED(port); - m0 = (struct rte_mbuf *)ev[0].mbuf; + m0 = ev[0].mbuf; qid = rte_event_eth_tx_adapter_txq_get(m0); + port_id = m0->port; + + /* The advertised enqueue depth is the EQCR size, which may exceed the + * on-stack burst array, so transmit in ring-sized chunks. + */ + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) + m[i] = ev[sent + i].mbuf; + + i = rte_eth_tx_burst(port_id, qid, m, burst); + sent += i; + if (i < burst) + break; + } - for (i = 0; i < nb_events; i++) - m[i] = (struct rte_mbuf *)ev[i].mbuf; - - return rte_eth_tx_burst(m0->port, qid, m, nb_events); + return sent; } static uint16_t @@ -996,19 +1007,28 @@ dpaa2_eventdev_txa_enqueue(void *port, struct rte_event ev[], uint16_t nb_events) { - void *txq[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - struct rte_mbuf *m[DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH]; - uint8_t qid, i; + void *txq[MAX_TX_RING_SLOTS]; + struct rte_mbuf *m[MAX_TX_RING_SLOTS]; + uint16_t sent = 0, burst, i; + uint8_t qid; RTE_SET_USED(port); - for (i = 0; i < nb_events; i++) { - m[i] = (struct rte_mbuf *)ev[i].mbuf; - qid = rte_event_eth_tx_adapter_txq_get(m[i]); - txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + while (sent < nb_events) { + burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); + for (i = 0; i < burst; i++) { + m[i] = ev[sent + i].mbuf; + qid = rte_event_eth_tx_adapter_txq_get(m[i]); + txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; + } + + i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); + sent += i; + if (i < burst) + break; } - return dpaa2_dev_tx_multi_txq_ordered(txq, m, nb_events); + return sent; } static struct eventdev_ops dpaa2_eventdev_ops = { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index 3883a26c91..a054dfdbd7 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2017 NXP + * Copyright 2017,2026 NXP */ #ifndef __DPAA2_EVENTDEV_H__ @@ -22,8 +22,6 @@ #define DPAA2_EVENT_MAX_QUEUE_FLOWS 2048 #define DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS 8 #define DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS 0 -#define DPAA2_EVENT_MAX_PORT_DEQUEUE_DEPTH 8 -#define DPAA2_EVENT_MAX_PORT_ENQUEUE_DEPTH 8 #define DPAA2_EVENT_MAX_NUM_EVENTS (INT32_MAX - 1) #define DPAA2_EVENT_QUEUE_ATOMIC_FLOWS 2048 -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 16/65] net/dpaa2: support multi-DPNI FS redirect and QoS table v3 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (14 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 15/65] bus/fslmc: align dpaa2 event port depths with hardware rings Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 17/65] net/dpaa2: rework xstats with page table and MAC support Prashant Gupta ` (48 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Pick up the newer MC command versions for the DPNI flow-steering and QoS table APIs, and expose the multi-DPNI redirect feature they add, while keeping the driver working against older MC firmwares. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 3 + drivers/net/dpaa2/dpaa2_flow.c | 27 +++++--- drivers/net/dpaa2/mc/dpni.c | 73 +++++++++++++++++----- drivers/net/dpaa2/mc/fsl_dpni.h | 95 +++++++++++++++++++++++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 30 +++++---- 5 files changed, 189 insertions(+), 39 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index ddc205c2d4..cc0292cd9c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -204,6 +204,9 @@ #define DPAA2_PKT_TYPE_VLAN \ (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) +#define DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 106) +#define DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV RTE_FSL_MC_REV(10, 39, 109) + /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) #define DPAA2_MAC_STATS_INDEX_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint32_t)) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 8e65faf75d..72958c0f93 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -539,10 +539,17 @@ dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, dpaa2_flow_fs_entry_log("Start add", flow); - ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, - priv->token, flow->tc_id, - flow->tc_index, &flow->fs_rule, - &flow->fs_action_cfg); + if (priv->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { + ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, + flow->tc_index, &flow->fs_rule, + &flow->fs_action_cfg); + } else { + ret = dpni_add_fs_entry_legacy(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, + flow->tc_index, &flow->fs_rule, + &flow->fs_action_cfg); + } if (ret < 0) { DPAA2_PMD_ERR("Add rule(%d) to FS table(%d) failed", flow->tc_index, flow->tc_id); @@ -4424,8 +4431,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, dest_q = dest_priv->tx_vq[0]; flow->fs_action_cfg.options = DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; - flow->fs_action_cfg.redirect_obj_token = - dest_priv->token; + flow->fs_action_cfg.num_tokens = 1; + flow->fs_action_cfg.redir_tokens[0] = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; @@ -4626,8 +4633,12 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, qos_cfg.default_tc = 0; } - ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, - priv->token, &qos_cfg); + if (priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) + ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, + priv->token, &qos_cfg); + else + ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, + priv->token, &qos_cfg); if (ret < 0) { DPAA2_PMD_ERR("QoS table set failed"); return ret; diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index 17275b7195..54df66416a 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #include <fsl_mc_sys.h> @@ -1937,32 +1937,43 @@ int dpni_get_queue_tx_confirmation_mode(struct fsl_mc_io *mc_io, * * Return: '0' on Success; Error code otherwise. */ -int dpni_set_qos_table(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - const struct dpni_qos_tbl_cfg *cfg) +static int +_dpni_set_qos_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg, uint16_t cmd_id) { struct dpni_cmd_set_qos_table *cmd_params; struct mc_command cmd = { 0 }; /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL, - cmd_flags, - token); - cmd_params = (struct dpni_cmd_set_qos_table *)cmd.params; + cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, token); + cmd_params = (void *)cmd.params; cmd_params->default_tc = cfg->default_tc; cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova); - dpni_set_field(cmd_params->discard_on_miss, - ENABLE, - cfg->discard_on_miss); - dpni_set_field(cmd_params->discard_on_miss, - KEEP_QOS_ENTRIES, - cfg->keep_entries); + if (DPNI_CMD_VER(cmd_id) > DPNI_CMD_VERSION_2) + cmd_params->default_flow_id = cpu_to_le16(cfg->default_flow_id); + dpni_set_field(cmd_params->flags, DISCARD_ON_MISS, cfg->discard_on_miss); + dpni_set_field(cmd_params->flags, KEEP_QOS_ENTRIES, cfg->keep_entries); + if (DPNI_CMD_VER(cmd_id) > DPNI_CMD_VERSION_2) + dpni_set_field(cmd_params->flags, SET_DEFAULT_FLOW_ID, cfg->set_default_flow_id); /* send command to mc*/ return mc_send_command(mc_io, &cmd); } +int +dpni_set_qos_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg) +{ + return _dpni_set_qos_table(mc_io, cmd_flags, token, cfg, DPNI_CMDID_SET_QOS_TBL); +} + +int +dpni_set_qos_table_v2(struct fsl_mc_io *mc_io, uint32_t cmd_flags, + uint16_t token, const struct dpni_qos_tbl_cfg *cfg) +{ + return _dpni_set_qos_table(mc_io, cmd_flags, token, cfg, DPNI_CMDID_SET_QOS_TBL_V2); +} + /** * dpni_add_qos_entry() - Add QoS mapping entry (to select a traffic class) * @mc_io: Pointer to MC portal's I/O object @@ -2086,6 +2097,7 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, { struct dpni_cmd_add_fs_entry *cmd_params; struct mc_command cmd = { 0 }; + int i; /* prepare command */ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT, @@ -2100,7 +2112,36 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, cmd_params->options = cpu_to_le16(action->options); cmd_params->flow_id = cpu_to_le16(action->flow_id); cmd_params->flc = cpu_to_le64(action->flc); - cmd_params->redir_token = cpu_to_le16(action->redirect_obj_token); + cmd_params->token_num = action->num_tokens; + for (i = 0; i < DPNI_FS_REDIR_MAX_NUM; i++) + cmd_params->redir_tokens[i] = cpu_to_le16(action->redir_tokens[i]); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} + +int dpni_add_fs_entry_legacy(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, + uint8_t tc_id, uint16_t index, + const struct dpni_rule_cfg *cfg, + const struct dpni_fs_action_cfg *action) +{ + struct dpni_cmd_add_fs_entry *cmd_params; + struct mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT_LEGACY, + cmd_flags, token); + cmd_params = (struct dpni_cmd_add_fs_entry *)cmd.params; + cmd_params->tc_id = tc_id; + cmd_params->key_size = cfg->key_size; + cmd_params->index = cpu_to_le16(index); + cmd_params->key_iova = cpu_to_le64(cfg->key_iova); + cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova); + cmd_params->options = cpu_to_le16(action->options); + cmd_params->flow_id = cpu_to_le16(action->flow_id); + cmd_params->flc = cpu_to_le64(action->flc); + cmd_params->redir_tokens[0] = cpu_to_le16(action->redir_tokens[0]); /* send command to mc*/ return mc_send_command(mc_io, &cmd); diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..f47f383a9b 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #ifndef __FSL_DPNI_H @@ -121,6 +121,9 @@ struct fsl_mc_io; * The stashing is enabled by default. */ #define DPNI_OPT_STASHING_DIS 0x002000 + +#define DPNI_OPT_V8_HAS_REPLICATION 0x00004000 + /* * PFDR in PEB mode (v1 layout). * The total number of Rx descriptors is limited to 11264 in this mode. @@ -1539,6 +1542,8 @@ struct dpni_qos_tbl_cfg { int discard_on_miss; int keep_entries; uint8_t default_tc; + int set_default_flow_id; + uint16_t default_flow_id; }; int dpni_set_qos_table(struct fsl_mc_io *mc_io, @@ -1546,6 +1551,11 @@ int dpni_set_qos_table(struct fsl_mc_io *mc_io, uint16_t token, const struct dpni_qos_tbl_cfg *cfg); +int dpni_set_qos_table_v2(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + const struct dpni_qos_tbl_cfg *cfg); + /** * struct dpni_rule_cfg - Rule configuration for table lookup * @key_iova: I/O virtual address of the key (must be in DMA-able memory) @@ -1558,6 +1568,10 @@ struct dpni_rule_cfg { uint8_t key_size; }; +#define DPNI_QOS_OPT_SET_TC_ONLY 0x0 +#define DPNI_QOS_OPT_SET_FLOW_ID 0x1 +#define DPNI_QOS_OPT_UPDATE_IF_EXISTS 0x2 + int dpni_add_qos_entry(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, @@ -1618,6 +1632,22 @@ int dpni_clear_qos_table(struct fsl_mc_io *mc_io, */ #define DPNI_FS_OPT_REDIRECT_TO_DPNI_TX 0x10 +/** + * Redirect matching traffic into multiple Tx queues of other dpni objects. + * The frame will be transmitted directly + */ +#define DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX 0x20 + +/** + * In case the FS rule already exists (key and mask), update its action. + * Cannot be used with the actions which redirect the frame towards other DPNIs. + */ +#define DPNI_FS_OPT_UPDATE_IF_EXISTS 0x40 + +#ifndef DPNI_FS_REDIR_MAX_NUM +#define DPNI_FS_REDIR_MAX_NUM 8 +#endif + /** * struct dpni_fs_action_cfg - Action configuration for table look-up * @flc: FLC value for traffic matching this rule. Please check the Frame @@ -1635,12 +1665,38 @@ int dpni_clear_qos_table(struct fsl_mc_io *mc_io, * - if DPNI_FS_OPT_DISCARD is cleared the frame will be enqueued in queue with * index provided in flow_id parameter. * @options: Any combination of DPNI_FS_OPT_ values. + * @token_num: Number of tokens supplied. For DPNI_FS_OPT_REDIRECT_TO_DPNI_RX + * or DPNI_FS_OPT_REDIRECT_TO_DPNI_TX, the token_num must be 1 since there is + * only one token which is necessary. Accepted values are in the + * [1-8] range in case a REDIRECT option is requested. + * @redir_tokens: Array of tokens that identify the object where frame is redirected + * when this rule is hit. This parameter is used only when one + * of the flags DPNI_FS_OPT_REDIRECT_TO_DPNI_RX, + * DPNI_FS_OPT_REDIRECT_TO_DPNI_TX or + * DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX is set. The tokens + * are obtained using dpni_open() API call. The objects must + * stay open during the operation to ensure the fact that + * application has access on them. + * If the object is destroyed of closed, the following actions + * will take place: + * - In case of DPNI_FS_OPT_REDIRECT_TO_DPNI_TX and + * DPNI_FS_OPT_REDIRECT_TO_DPNI_RX: + * + if DPNI_FS_OPT_DISCARD is set the frame will be + * discarded by current dpni + * + if DPNI_FS_OPT_DISCARD is cleared the frame will be + * enqueued in queue with index provided in flow_id + * parameter. + * - In case of DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX, the + * frame will be redirected to the remaining opened target + * DPNIs. If there are no more opened target DPNIs, the frame + * will be discarded. */ struct dpni_fs_action_cfg { uint64_t flc; uint16_t flow_id; - uint16_t redirect_obj_token; uint16_t options; + uint16_t num_tokens; + uint16_t redir_tokens[DPNI_FS_REDIR_MAX_NUM]; }; int dpni_add_fs_entry(struct fsl_mc_io *mc_io, @@ -1651,6 +1707,14 @@ int dpni_add_fs_entry(struct fsl_mc_io *mc_io, const struct dpni_rule_cfg *cfg, const struct dpni_fs_action_cfg *action); +int dpni_add_fs_entry_legacy(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + uint16_t index, + const struct dpni_rule_cfg *cfg, + const struct dpni_fs_action_cfg *action); + int dpni_remove_fs_entry(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, @@ -1913,7 +1977,7 @@ void dpni_extract_sw_sequence_layout(struct dpni_sw_sequence_layout *layout, * When used for queue_idx in function dpni_set_rx_dist_default_queue will signal to dpni * to drop all unclassified frames */ -#define DPNI_FS_MISS_DROP ((uint16_t)-1) +#define DPNI_FS_MISS_ACTION_DROP ((uint16_t)-1) /** * struct dpni_rx_dist_cfg - distribution configuration @@ -1926,7 +1990,7 @@ void dpni_extract_sw_sequence_layout(struct dpni_sw_sequence_layout *layout, * @enable: enable/disable the distribution. * @tc: TC id for which distribution is set * @fs_miss_flow_id: when packet misses all rules from flow steering table and hash is - * disabled it will be put into this queue id; use DPNI_FS_MISS_DROP to drop + * disabled it will be put into this queue id; use DPNI_FS_MISS_ACTION_DROP to drop * frames. The value of this field is used only when flow steering distribution * is enabled and hash distribution is disabled */ @@ -2020,6 +2084,29 @@ enum dpni_table_type { DPNI_VLAN_TABLE = 4, }; +struct __rte_packed_begin dpni_dump_table_header { + uint16_t table_type; + uint16_t table_num_entries; + uint16_t table_max_entries; + uint8_t default_action; + uint8_t match_type; + uint8_t reserved[24]; +} __rte_packed_end; + +struct __rte_packed_begin dpni_dump_table_entry { + uint8_t key[DPNI_MAX_KEY_SIZE]; + uint8_t mask[DPNI_MAX_KEY_SIZE]; + uint8_t key_action; + uint16_t result[3]; + uint16_t rule_index; + uint8_t reserved[19]; +} __rte_packed_end; + +struct __rte_packed_begin dpni_dump_table_rsp { + struct dpni_dump_table_header hdr; + struct dpni_dump_table_entry entry[]; +} __rte_packed_end; + int dpni_dump_table(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index 6b396ca7cc..36e4aacc3a 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2016-2025 NXP + * Copyright 2016-2026 NXP * */ #ifndef _FSL_DPNI_CMD_H @@ -20,6 +20,7 @@ #define DPNI_CMD_VERSION_7 7 #define DPNI_CMD_ID_OFFSET 4 +#define DPNI_CMD_VER(cmd_id) ((cmd_id) & ((1 << DPNI_CMD_ID_OFFSET) - 1)) #define DPNI_CMD(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_BASE_VERSION) #define DPNI_CMD_V2(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_VERSION_2) #define DPNI_CMD_V3(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_VERSION_3) @@ -77,13 +78,16 @@ #define DPNI_CMDID_SET_RX_TC_DIST DPNI_CMD_V4(0x235) -#define DPNI_CMDID_SET_RX_TC_POLICING DPNI_CMD(0x23E) +#define DPNI_CMDID_SET_RX_TC_POLICING_V1 DPNI_CMD(0x23E) +#define DPNI_CMDID_SET_RX_TC_POLICING DPNI_CMD_V2(0x23E) -#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD_V2(0x240) +#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD_V3(0x240) +#define DPNI_CMDID_SET_QOS_TBL_V2 DPNI_CMD_V2(0x240) #define DPNI_CMDID_ADD_QOS_ENT DPNI_CMD_V2(0x241) #define DPNI_CMDID_REMOVE_QOS_ENT DPNI_CMD(0x242) #define DPNI_CMDID_CLR_QOS_TBL DPNI_CMD(0x243) -#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD_V2(0x244) +#define DPNI_CMDID_ADD_FS_ENT_LEGACY DPNI_CMD_V2(0x244) +#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD_V3(0x244) #define DPNI_CMDID_REMOVE_FS_ENT DPNI_CMD(0x245) #define DPNI_CMDID_CLR_FS_ENT DPNI_CMD(0x246) @@ -584,19 +588,18 @@ struct dpni_cmd_set_queue { #define DPNI_DISCARD_ON_MISS_SIZE 1 #define DPNI_KEEP_QOS_ENTRIES_SHIFT 1 #define DPNI_KEEP_QOS_ENTRIES_SIZE 1 +#define DPNI_SET_DEFAULT_FLOW_ID_SHIFT 2 +#define DPNI_SET_DEFAULT_FLOW_ID_SIZE 1 struct dpni_cmd_set_qos_table { - uint32_t pad; + uint16_t pad; + uint16_t default_flow_id; uint8_t default_tc; - /* only the LSB */ - uint8_t discard_on_miss; + uint8_t flags; uint16_t pad1[21]; uint64_t key_cfg_iova; }; -#define DPNI_QOS_OPT_SET_TC_ONLY 0x0 -#define DPNI_QOS_OPT_SET_FLOW_ID 0x1 - struct dpni_cmd_add_qos_entry { uint8_t flags; uint8_t flow_id; @@ -616,6 +619,10 @@ struct dpni_cmd_remove_qos_entry { uint64_t mask_iova; }; +#ifndef DPNI_FS_REDIR_MAX_NUM +#define DPNI_FS_REDIR_MAX_NUM 8 +#endif + struct dpni_cmd_add_fs_entry { uint16_t options; uint8_t tc_id; @@ -625,7 +632,8 @@ struct dpni_cmd_add_fs_entry { uint64_t key_iova; uint64_t mask_iova; uint64_t flc; - uint16_t redir_token; + uint16_t redir_tokens[DPNI_FS_REDIR_MAX_NUM]; + uint8_t token_num; }; struct dpni_cmd_remove_fs_entry { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 17/65] net/dpaa2: rework xstats with page table and MAC support 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (15 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 16/65] net/dpaa2: support multi-DPNI FS redirect and QoS table v3 Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 18/65] net/dpaa2: unify xstats layout and add DPMAC counter struct Prashant Gupta ` (47 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Breeson Francis, Jun Yang From: Breeson Francis <breeson.francis@nokia.com> Reshape DPAA2 xstats so that counter identity is derived from the DPNI statistics page layout itself instead of a hand-maintained parallel table, extend coverage to all DPNI pages (0..6, including CEETM and tx-pending), expose per-MAC counters when the endpoint is a DPMAC on MC firmware that supports it, and make xstats_get_by_id() actually cheap when a caller asks for a subset of IDs. Signed-off-by: Breeson Francis <breeson.francis@nokia.com> Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 1004 +++++++++++++++++++----------- drivers/net/dpaa2/dpaa2_ethdev.h | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 116 ++-- 3 files changed, 708 insertions(+), 423 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0fbc2c77b0..e7ac6b7dad 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -169,116 +169,290 @@ dpaa2_dist_size_is_supported(uint16_t n) int dpaa2_valid_dev; struct rte_mempool *dpaa2_tx_sg_pool; -struct rte_dpaa2_xstats_name_off { +struct dpaa2_dpni_xstats_pg_seq { + struct dpni_statistics_page_0 pg0; + struct dpni_statistics_page_1 pg1; + struct dpni_statistics_page_2 pg2; + struct dpni_statistics_page_3 pg3; + struct dpni_statistics_page_4 pg4; + struct dpni_statistics_page_5 pg5[MAX_TCS]; + struct dpni_statistics_page_6 pg6; +}; + +#define DPAA2_DPNI_XSTAT_MAX_NUM \ + (sizeof(struct dpaa2_dpni_xstats_pg_seq) / sizeof(uint64_t)) + +struct dpaa2_dpni_xstats_pg { + uint64_t page_offset; + enum dpni_statistics_page_id page_id; + uint16_t param; + uint16_t size; +}; + +static const struct dpaa2_dpni_xstats_pg s_dpaa2_dpni_xstats_pgs[] = { + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg0), + DPNI_INGRESS_STATISTICS_PAGE_ID, 0, + sizeof(struct dpni_statistics_page_0) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg1), + DPNI_EGRESS_STATISTICS_PAGE_ID, 0, + sizeof(struct dpni_statistics_page_1) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg2), + DPNI_ERR_STATISTICS_PAGE_ID, 0, + sizeof(struct dpni_statistics_page_2) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg3), + DPNI_CEETM_STATISTICS_PAGE_ID, 0, + sizeof(struct dpni_statistics_page_3) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg4), + DPNI_CGR_STATISTICS_PAGE_ID, 0, + sizeof(struct dpni_statistics_page_4) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[0]), + DPNI_POLICER_STATISTICS_PAGE_ID, 0, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[1]), + DPNI_POLICER_STATISTICS_PAGE_ID, 1, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[2]), + DPNI_POLICER_STATISTICS_PAGE_ID, 2, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[3]), + DPNI_POLICER_STATISTICS_PAGE_ID, 3, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[4]), + DPNI_POLICER_STATISTICS_PAGE_ID, 4, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[5]), + DPNI_POLICER_STATISTICS_PAGE_ID, 5, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[6]), + DPNI_POLICER_STATISTICS_PAGE_ID, 6, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[7]), + DPNI_POLICER_STATISTICS_PAGE_ID, 7, + sizeof(struct dpni_statistics_page_5) + }, + { + offsetof(struct dpaa2_dpni_xstats_pg_seq, pg6), + DPNI_TX_PENDING_STATISTICS_PAGE_ID, 0, + sizeof(struct dpni_statistics_page_6) + }, + { + sizeof(struct dpaa2_dpni_xstats_pg_seq), + 0, 0, 0 + } +}; + +static inline int +dpaa2_xstats_id_parse(uint32_t id, uint8_t *page, + uint8_t *stat_id, uint16_t *param, uint16_t *size) +{ + int found = 0; + uint8_t _page = 0, _stat_id = 0; + uint16_t _param = 0, _size = 0; + uint64_t offset = id * sizeof(uint64_t), page_offset = 0, i; + + for (i = 1; i < RTE_DIM(s_dpaa2_dpni_xstats_pgs); i++) { + if (offset < s_dpaa2_dpni_xstats_pgs[i].page_offset) { + page_offset = s_dpaa2_dpni_xstats_pgs[i - 1].page_offset; + _page = s_dpaa2_dpni_xstats_pgs[i - 1].page_id; + _stat_id = (offset - page_offset) / sizeof(uint64_t); + _param = s_dpaa2_dpni_xstats_pgs[i - 1].param; + _size = s_dpaa2_dpni_xstats_pgs[i - 1].size / sizeof(uint64_t); + found = 1; + break; + } + } + + if (!found) + return -EINVAL; + + if (page) + *page = _page; + if (stat_id) + *stat_id = _stat_id; + if (param) + *param = _param; + if (size) + *size = _size; + + return 0; +} + +struct dpaa2_stats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; - uint8_t page_id; /* dpni statistics page id */ - uint8_t stats_id; /* stats id in the given page */ + uint64_t offset; +}; + +#define DPAA2_STATS_IPACKETS_STR "ingress_all_frames" +#define DPAA2_STATS_OPACKETS_STR "egress_all_frames" +#define DPAA2_STATS_IBYTES_STR "ingress_all_bytes" +#define DPAA2_STATS_OBYTES_STR "egress_all_bytes" +#define DPAA2_STATS_IERRORS_STR "ingress_discarded_frames" +#define DPAA2_STATS_OERRORS_STR "egress_discarded_frames" +#define DPAA2_STATS_RX_NOMBUF_STR "ingress_nobuffer_discards" +#define DPAA2_STATS_FILTERED_STR "ingress_filtered_frames" + +static const struct dpaa2_stats_name_off dpaa2_stats_strings[] = { + { + DPAA2_STATS_IPACKETS_STR, + offsetof(struct rte_eth_stats, ipackets) + }, + { + DPAA2_STATS_OPACKETS_STR, + offsetof(struct rte_eth_stats, opackets) + }, + { + DPAA2_STATS_IBYTES_STR, + offsetof(struct rte_eth_stats, ibytes) + }, + { + DPAA2_STATS_OBYTES_STR, + offsetof(struct rte_eth_stats, obytes) + }, + { + DPAA2_STATS_FILTERED_STR, + sizeof(struct rte_eth_stats) + }, + { + DPAA2_STATS_IERRORS_STR, + offsetof(struct rte_eth_stats, ierrors) + }, + { + DPAA2_STATS_OERRORS_STR, + offsetof(struct rte_eth_stats, oerrors) + }, + { + DPAA2_STATS_RX_NOMBUF_STR, + offsetof(struct rte_eth_stats, rx_nombuf) + } }; -static const struct rte_dpaa2_xstats_name_off dpaa2_xstats_strings[] = { - {"ingress_multicast_frames", 0, 2}, - {"ingress_multicast_bytes", 0, 3}, - {"ingress_broadcast_frames", 0, 4}, - {"ingress_broadcast_bytes", 0, 5}, - {"egress_multicast_frames", 1, 2}, - {"egress_multicast_bytes", 1, 3}, - {"egress_broadcast_frames", 1, 4}, - {"egress_broadcast_bytes", 1, 5}, - {"ingress_filtered_frames", 2, 0}, - {"ingress_discarded_frames", 2, 1}, - {"ingress_nobuffer_discards", 2, 2}, - {"egress_discarded_frames", 2, 3}, - {"egress_confirmed_frames", 2, 4}, - {"cgr_reject_frames", 4, 0}, - {"cgr_reject_bytes", 4, 1}, - {"TC_0_policer_cnt_red", 5, 0}, - {"TC_0_policer_cnt_yellow", 5, 1}, - {"TC_0_policer_cnt_green", 5, 2}, - {"TC_0_policer_cnt_re_red", 5, 3}, - {"TC_0_policer_cnt_re_yellow", 5, 4}, - {"TC_1_policer_cnt_red", 6, 0}, - {"TC_1_policer_cnt_yellow", 6, 1}, - {"TC_1_policer_cnt_green", 6, 2}, - {"TC_1_policer_cnt_re_red", 6, 3}, - {"TC_1_policer_cnt_re_yellow", 6, 4}, - {"TC_2_policer_cnt_red", 7, 0}, - {"TC_2_policer_cnt_yellow", 7, 1}, - {"TC_2_policer_cnt_green", 7, 2}, - {"TC_2_policer_cnt_re_red", 7, 3}, - {"TC_2_policer_cnt_re_yellow", 7, 4}, - {"TC_3_policer_cnt_red", 8, 0}, - {"TC_3_policer_cnt_yellow", 8, 1}, - {"TC_3_policer_cnt_green", 8, 2}, - {"TC_3_policer_cnt_re_red", 8, 3}, - {"TC_3_policer_cnt_re_yellow", 8, 4}, - {"TC_4_policer_cnt_red", 9, 0}, - {"TC_4_policer_cnt_yellow", 9, 1}, - {"TC_4_policer_cnt_green", 9, 2}, - {"TC_4_policer_cnt_re_red", 9, 3}, - {"TC_4_policer_cnt_re_yellow", 9, 4}, - {"TC_5_policer_cnt_red", 10, 0}, - {"TC_5_policer_cnt_yellow", 10, 1}, - {"TC_5_policer_cnt_green", 10, 2}, - {"TC_5_policer_cnt_re_red", 10, 3}, - {"TC_5_policer_cnt_re_yellow", 10, 4}, - {"TC_6_policer_cnt_red", 11, 0}, - {"TC_6_policer_cnt_yellow", 11, 1}, - {"TC_6_policer_cnt_green", 11, 2}, - {"TC_6_policer_cnt_re_red", 11, 3}, - {"TC_6_policer_cnt_re_yellow", 11, 4}, - {"TC_7_policer_cnt_red", 12, 0}, - {"TC_7_policer_cnt_yellow", 12, 1}, - {"TC_7_policer_cnt_green", 12, 2}, - {"TC_7_policer_cnt_re_red", 12, 3}, - {"TC_7_policer_cnt_re_yellow", 12, 4}, - {"mac_rx_64 bytes", 0, 0}, - {"mac_rx_65-127 bytes", 0, 0}, - {"mac_rx_128-255 bytes", 0, 0}, - {"mac_rx_256-511 bytes", 0, 0}, - {"mac_rx_512-1023 bytes", 0, 0}, - {"mac_rx_1024-1518 bytes", 0, 0}, - {"mac_rx_1519-max bytes", 0, 0}, - {"mac_rx_frags", 0, 0}, - {"mac_rx_jabber", 0, 0}, - {"mac_rx_frame discards", 0, 0}, - {"mac_rx_align errors", 0, 0}, - {"mac_tx_undersized", 0, 0}, - {"mac_rx_oversized", 0, 0}, - {"mac_rx_pause", 0, 0}, - {"mac_tx_b-pause", 0, 0}, - {"mac_rx_bytes", 0, 0}, - {"mac_rx_m-cast", 0, 0}, - {"mac_rx_b-cast", 0, 0}, - {"mac_rx_all frames", 0, 0}, - {"mac_rx_u-cast", 0, 0}, - {"mac_rx_frame errors", 0, 0}, - {"mac_tx_bytes", 0, 0}, - {"mac_tx_m-cast", 0, 0}, - {"mac_tx_b-cast", 0, 0}, - {"mac_tx_u-cast", 0, 0}, - {"mac_tx_frame errors", 0, 0}, - {"mac_rx_frames ok", 0, 0}, - {"mac_tx_frames ok", 0, 0}, - {"mac_tx_64 bytes", 0, 0}, - {"mac_tx_65-127 bytes", 0, 0}, - {"mac_tx_128-255 bytes", 0, 0}, - {"mac_tx_256-511 bytes", 0, 0}, - {"mac_tx_512-1023 bytes", 0, 0}, - {"mac_tx_1024-1518 bytes", 0, 0}, - {"mac_tx_1519-max bytes", 0, 0}, - {"mac_rx_all_bytes", 0, 0}, - {"mac_rx_fcs_err", 0, 0}, - {"mac_rx_vlan_frame", 0, 0}, - {"mac_rx_undersized", 0, 0}, - {"mac_rx_control_frame", 0, 0}, - {"mac_rx_frame_discard_not_trunc", 0, 0}, - {"mac_tx_all_bytes", 0, 0}, - {"mac_tx_fcs_err", 0, 0}, - {"mac_tx_vlan_frame", 0, 0}, - {"mac_tx_all_frame", 0, 0}, - {"mac_tx_control_frame", 0, 0}, +#define DPAA2_STATS_SET_BY_OFFSET(p_stats, offset, val) \ + (*((uint64_t *)((uint8_t *)(p_stats) + (offset))) = (val)) + +#define DPAA2_TC_COLOR(tc) \ + "TC_"#tc"_policer_cnt_red", \ + "TC_"#tc"_policer_cnt_yellow", \ + "TC_"#tc"_policer_cnt_green", \ + "TC_"#tc"_policer_cnt_re_red", \ + "TC_"#tc"_policer_cnt_re_yellow" \ + +static const char * const dpaa2_dpni_xstats_strings[] = { + DPAA2_STATS_IPACKETS_STR, + DPAA2_STATS_IBYTES_STR, + "ingress_multicast_frames", + "ingress_multicast_bytes", + "ingress_broadcast_frames", + "ingress_broadcast_bytes", + + DPAA2_STATS_OPACKETS_STR, + DPAA2_STATS_OBYTES_STR, + "egress_multicast_frames", + "egress_multicast_bytes", + "egress_broadcast_frames", + "egress_broadcast_bytes", + + DPAA2_STATS_FILTERED_STR, + DPAA2_STATS_IERRORS_STR, + DPAA2_STATS_RX_NOMBUF_STR, + DPAA2_STATS_OERRORS_STR, + "egress_confirmed_frames", + + "cgr_reject_frames", + "cgr_reject_bytes", + + "ceetm_dequeue_bytes", + "ceetm_dequeue_frames", + "ceetm_reject_bytes", + "ceetm_reject_frames", + DPAA2_TC_COLOR(0), + DPAA2_TC_COLOR(1), + DPAA2_TC_COLOR(2), + DPAA2_TC_COLOR(3), + DPAA2_TC_COLOR(4), + DPAA2_TC_COLOR(5), + DPAA2_TC_COLOR(6), + DPAA2_TC_COLOR(7), + + "tx_pending_frames_cnt" }; +static const char * const dpaa2_mac_xstats_strings[] = { + "mac_rx_64 bytes", + "mac_rx_65-127 bytes", + "mac_rx_128-255 bytes", + "mac_rx_256-511 bytes", + "mac_rx_512-1023 bytes", + "mac_rx_1024-1518 bytes", + "mac_rx_1519-max bytes", + "mac_rx_frags", + "mac_rx_jabber", + "mac_rx_frame discards", + "mac_rx_align errors", + "mac_tx_undersized", + "mac_rx_oversized", + "mac_rx_pause", + "mac_tx_b-pause", + "mac_rx_bytes", + "mac_rx_m-cast", + "mac_rx_b-cast", + "mac_rx_all frames", + "mac_rx_u-cast", + "mac_rx_frame errors", + "mac_tx_bytes", + "mac_tx_m-cast", + "mac_tx_b-cast", + "mac_tx_u-cast", + "mac_tx_frame errors", + "mac_rx_frames ok", + "mac_tx_frames ok", + "mac_tx_64 bytes", + "mac_tx_65-127 bytes", + "mac_tx_128-255 bytes", + "mac_tx_256-511 bytes", + "mac_tx_512-1023 bytes", + "mac_tx_1024-1518 bytes", + "mac_tx_1519-max bytes", + "mac_rx_all_bytes", + "mac_rx_fcs_err", + "mac_rx_vlan_frame", + "mac_rx_undersized", + "mac_rx_control_frame", + "mac_rx_frame_discard_not_trunc", + "mac_tx_all_bytes", + "mac_tx_fcs_err", + "mac_tx_vlan_frame", + "mac_tx_all_frame", + "mac_tx_control_frame" +}; + +#define DPAA2_MAC_XSTATS_START_ID \ + (sizeof(struct dpaa2_dpni_xstats_pg_seq) / sizeof(uint64_t)) + static struct rte_dpaa2_driver rte_dpaa2_pmd; static int dpaa2_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); @@ -1958,132 +2132,97 @@ dpaa2_dev_set_mac_addr(struct rte_eth_dev *dev, } static int -dpaa2_dev_stats_get(struct rte_eth_dev *dev, - struct rte_eth_stats *stats, struct eth_queue_stats *qstats) +dpaa2_dev_xstat_mac_setup_mem(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - int32_t retcode; - uint8_t page0 = 0, page1 = 1, page2 = 2; - union dpni_statistics value; - int i; - struct dpaa2_queue *dpaa2_rxq, *dpaa2_txq; - - memset(&value, 0, sizeof(union dpni_statistics)); - - PMD_INIT_FUNC_TRACE(); + uint32_t *cnt_idx, i; + int ret = 0; - if (!dpni) { - DPAA2_PMD_ERR("dpni is NULL"); - return -EINVAL; - } + if (!priv->cnt_idx_dma_mem) { + priv->cnt_idx_dma_mem = rte_zmalloc(NULL, + DPAA2_MAC_STATS_INDEX_DMA_SIZE, RTE_CACHE_LINE_SIZE); + if (!priv->cnt_idx_dma_mem) { + ret = -ENOMEM; + DPAA2_PMD_ERR("Failure to allocate memory for mac index"); + goto out; + } - if (!stats) { - DPAA2_PMD_ERR("stats is NULL"); - return -EINVAL; + priv->cnt_idx_iova = rte_mem_virt2iova(priv->cnt_idx_dma_mem); + if (priv->cnt_idx_iova == RTE_BAD_IOVA) { + ret = -ENOBUFS; + DPAA2_PMD_ERR("%s: No IOMMU map for count index dma mem(%p)", + __func__, priv->cnt_idx_dma_mem); + goto err_dma_map; + } + cnt_idx = priv->cnt_idx_dma_mem; + for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) + cnt_idx[i] = rte_cpu_to_le_32(i); } - /*Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page0, 0, &value); - if (retcode) - goto err; - - stats->ipackets = value.page_0.ingress_all_frames; - stats->ibytes = value.page_0.ingress_all_bytes; - - /*Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page1, 0, &value); - if (retcode) - goto err; - - stats->opackets = value.page_1.egress_all_frames; - stats->obytes = value.page_1.egress_all_bytes; - - /*Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - page2, 0, &value); - if (retcode) - goto err; - - /* Ingress drop frame count due to configured rules */ - stats->ierrors = value.page_2.ingress_filtered_frames; - /* Ingress drop frame count due to error */ - stats->ierrors += value.page_2.ingress_discarded_frames; - - stats->oerrors = value.page_2.egress_discarded_frames; - stats->imissed = value.page_2.ingress_nobuffer_discards; - - /* Fill in per queue stats. Byte counting is not implemented. */ - if (qstats != NULL) { - for (i = 0; i < dev->data->nb_rx_queues; ++i) { - dpaa2_rxq = priv->rx_vq[i]; - if (dpaa2_rxq) - qstats[i].q_ipackets = dpaa2_rxq->rx_pkts; + if (!priv->cnt_values_dma_mem) { + priv->cnt_values_dma_mem = rte_zmalloc(NULL, + DPAA2_MAC_STATS_VALUE_DMA_SIZE, RTE_CACHE_LINE_SIZE); + if (!priv->cnt_values_dma_mem) { + ret = -ENOMEM; + DPAA2_PMD_ERR("Failure to allocate memory for mac values"); + goto err_alloc_values; } - for (i = 0; i < dev->data->nb_tx_queues; ++i) { - dpaa2_txq = priv->tx_vq[i]; - if (dpaa2_txq) - qstats[i].q_opackets = dpaa2_txq->tx_pkts; + priv->cnt_values_iova = rte_mem_virt2iova(priv->cnt_values_dma_mem); + if (priv->cnt_values_iova == RTE_BAD_IOVA) { + ret = -ENOBUFS; + DPAA2_PMD_ERR("%s: No IOMMU map for count values dma mem(%p)", + __func__, priv->cnt_values_dma_mem); + goto err_dma_map; } } return 0; -err: - DPAA2_PMD_ERR("Operation not completed:Error Code = %d", retcode); - return retcode; -}; +err_dma_map: + rte_free(priv->cnt_values_dma_mem); +err_alloc_values: + rte_free(priv->cnt_idx_dma_mem); +out: + priv->cnt_idx_dma_mem = NULL; + priv->cnt_values_dma_mem = NULL; -void -dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev) + return ret; +} + +static int +dpaa2_dev_mac_xstats_avail(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint32_t *cnt_idx; - int i; - - priv->cnt_idx_dma_mem = rte_malloc(NULL, DPAA2_MAC_STATS_INDEX_DMA_SIZE, - RTE_CACHE_LINE_SIZE); - if (!priv->cnt_idx_dma_mem) { - DPAA2_PMD_ERR("Failure to allocate memory for mac index"); - goto out; - } - priv->cnt_values_dma_mem = rte_malloc(NULL, DPAA2_MAC_STATS_VALUE_DMA_SIZE, - RTE_CACHE_LINE_SIZE); - if (!priv->cnt_values_dma_mem) { - DPAA2_PMD_ERR("Failure to allocate memory for mac values"); - goto err_alloc_values; - } + if (priv->ep_dev_type != DPAA2_MAC) + return false; + if (priv->mc_rev < DPAA2_MAC_XSTATS_MC_REV) + return false; - cnt_idx = priv->cnt_idx_dma_mem; - for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) - *cnt_idx++ = rte_cpu_to_le_32((uint32_t)i); + return true; +} - priv->cnt_idx_iova = rte_mem_virt2iova(priv->cnt_idx_dma_mem); - if (priv->cnt_idx_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for count index dma mem(%p)", - __func__, priv->cnt_idx_dma_mem); - goto err_dma_map; - } +static int +dpaa2_dev_dpni_xstats_avail(struct rte_eth_dev *dev, + uint8_t page_id, uint16_t param) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + uint8_t tc, i; - priv->cnt_values_iova = rte_mem_virt2iova(priv->cnt_values_dma_mem); - if (priv->cnt_values_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for count values dma mem(%p)", - __func__, priv->cnt_values_dma_mem); - goto err_dma_map; + if (page_id == DPNI_CGR_STATISTICS_PAGE_ID) { + for (i = 0; i < priv->max_cgs; i++) { + if (priv->cgid_in_use[i]) + return true; + } + } else if (page_id == DPNI_POLICER_STATISTICS_PAGE_ID) { + tc = param; + if (tc < MAX_TCS) + return true; + } else { + return true; } - return; - -err_dma_map: - rte_free(priv->cnt_values_dma_mem); -err_alloc_values: - rte_free(priv->cnt_idx_dma_mem); -out: - priv->cnt_idx_dma_mem = NULL; - priv->cnt_values_dma_mem = NULL; + return false; } /* @@ -2093,213 +2232,343 @@ dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev) */ static int dpaa2_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstat *xstats, unsigned int n) + struct rte_eth_xstat *xstats, uint32_t n) { - struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; - unsigned int i = 0, j = 0, num = RTE_DIM(dpaa2_xstats_strings); + struct fsl_mc_io *dpni = dev->process_private; + uint16_t i, j, param, stat_cnt, size; struct dpaa2_dev_priv *priv = dev->data->dev_private; - union dpni_statistics value[13] = {}; - struct dpni_rx_tc_policing_cfg cfg; - uint8_t page_id, stats_id; + union dpni_statistics values; + uint8_t page_id, stat_id; uint64_t *cnt_values; - int32_t retcode; - int16_t tc; + int retcode; + + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (priv->ep_dev_type == DPAA2_MAC) + stat_cnt += DPAA2_MAC_NUM_STATS; - if (n < num) - return num; + if (n > stat_cnt) { + DPAA2_PMD_ERR("%s: Expected number(%d) > max number(%d)", + __func__, n, stat_cnt); + return -EINVAL; + } if (!xstats) return 0; - /* Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 0, 0, &value[0]); - if (retcode) - goto err; - - /* Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 1, 0, &value[1]); - if (retcode) - goto err; - - /* Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 2, 0, &value[2]); - if (retcode) - goto err; - - for (j = 0; j < priv->max_cgs; j++) { - if (!priv->cgid_in_use[j]) { - /* Get Counters from page_4*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, - priv->token, - 4, 0, &value[4]); - if (retcode) - goto err; - break; + i = 0; + while (i < n) { + if (i >= DPAA2_MAC_XSTATS_START_ID) { + if (!dpaa2_dev_mac_xstats_avail(dev)) { + for (j = i; j < n; j++) { + xstats[j].id = j; + xstats[j].value = 0; + } + i = n; + break; + } + goto dpmac_get_xstat; } - } - for (tc = 0; tc < priv->num_rx_tc; tc++) { - retcode = dpni_get_rx_tc_policing(dpni, CMD_PRI_LOW, - priv->token, tc, - &cfg); + page_id = 0; + stat_id = 0; + param = 0; + retcode = dpaa2_xstats_id_parse(i, &page_id, &stat_id, ¶m, &size); + if (retcode) + return retcode; + if (!dpaa2_dev_dpni_xstats_avail(dev, page_id, param)) { + xstats[i].id = i; + xstats[i].value = 0; + i++; + continue; + } + retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, + priv->token, page_id, param, &values); if (retcode) { - DPAA2_PMD_ERR("Error to get the policer rule: %d", retcode); - goto err; + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's statistcis of page%d!", + __func__, retcode, dev->data->name, page_id); + return retcode; } - - /* get policer stats if policer is enabled */ - if (cfg.mode != 0) { - /* Get Counters from page_5*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, - priv->token, 5, tc, - &value[(tc + 5)]); - if (retcode) - goto err; + cnt_values = (void *)&values; + j = stat_id; + while (i < n && j < size) { + xstats[i].id = i; + xstats[i].value = cnt_values[j]; + i++; + j++; } - } + continue; - while (i < (num - DPAA2_MAC_NUM_STATS)) { - xstats[i].id = i; - page_id = dpaa2_xstats_strings[i].page_id; - stats_id = dpaa2_xstats_strings[i].stats_id; - xstats[i].value = value[page_id].raw.counter[stats_id]; - i++; - } - - if (priv->cnt_idx_dma_mem && - !dpni_get_mac_statistics(dpni, CMD_PRI_LOW, priv->token, - priv->cnt_idx_iova, - priv->cnt_values_iova, - DPAA2_MAC_NUM_STATS)) { +dpmac_get_xstat: + retcode = dpaa2_dev_xstat_mac_setup_mem(dev); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to setup %s MAC statistics!", + __func__, retcode, dev->data->name); + return retcode; + } + retcode = dpni_get_mac_statistics(dpni, CMD_PRI_LOW, + priv->token, priv->cnt_idx_iova, + priv->cnt_values_iova, DPAA2_MAC_NUM_STATS); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's MAC statistics!", + __func__, retcode, dev->data->name); + return retcode; + } cnt_values = priv->cnt_values_dma_mem; - while (i >= (num - DPAA2_MAC_NUM_STATS) && i < num) { + + j = i - DPAA2_MAC_XSTATS_START_ID; + while (i < n && j < DPAA2_MAC_NUM_STATS) { xstats[i].id = i; - xstats[i].value = rte_le_to_cpu_64(*cnt_values++); + xstats[i].value = cnt_values[j]; i++; + j++; } - return i; - } - - while (i >= (num - DPAA2_MAC_NUM_STATS) && i < num) { - xstats[i].id = i; - xstats[i].value = 0; - i++; } return i; -err: - DPAA2_PMD_ERR("Error in obtaining extended stats (%d)", retcode); - return retcode; } static int -dpaa2_xstats_get_names(__rte_unused struct rte_eth_dev *dev, - struct rte_eth_xstat_name *xstats_names, - unsigned int limit) +dpaa2_dev_xstats_get_names(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, uint32_t limit) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); + struct dpaa2_dev_priv *priv = dev->data->dev_private; + uint16_t i, stat_cnt; + + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (priv->ep_dev_type == DPAA2_MAC) + stat_cnt += DPAA2_MAC_NUM_STATS; + + if (!limit) + return stat_cnt; if (limit < stat_cnt) + stat_cnt = limit; + + if (!xstats_names) return stat_cnt; - if (xstats_names != NULL) - for (i = 0; i < stat_cnt; i++) - strlcpy(xstats_names[i].name, - dpaa2_xstats_strings[i].name, - sizeof(xstats_names[i].name)); + for (i = 0; i < stat_cnt; i++) { + if (i < DPAA2_DPNI_XSTAT_MAX_NUM) { + rte_strscpy(xstats_names[i].name, dpaa2_dpni_xstats_strings[i], + RTE_ETH_XSTATS_NAME_SIZE); + } else { + rte_strscpy(xstats_names[i].name, + dpaa2_mac_xstats_strings[i - DPAA2_DPNI_XSTAT_MAX_NUM], + RTE_ETH_XSTATS_NAME_SIZE); + } + } return stat_cnt; } static int -dpaa2_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, - uint64_t *values, unsigned int n) +dpaa2_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, + uint64_t *values, uint32_t n) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); - uint64_t values_copy[stat_cnt]; - uint8_t page_id, stats_id; - - if (!ids) { - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - int32_t retcode; - union dpni_statistics value[5] = {}; + uint16_t i, id, stat_cnt; + uint8_t page_id, stat_id; + uint16_t param; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = dev->process_private; + bool page_fetched[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; + /* Fetch all MAC counters in a single MC command on first MAC xstat. */ + bool mac_fetched = false; + int retcode; + uint64_t *cnt_values; - if (n < stat_cnt) - return stat_cnt; + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (priv->ep_dev_type == DPAA2_MAC) + stat_cnt += DPAA2_MAC_NUM_STATS; - if (!values) - return 0; + memset(page_fetched, 0, sizeof(page_fetched)); - /* Get Counters from page_0*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 0, 0, &value[0]); + for (i = 0; i < n; i++) { + if (ids && ids[i] >= stat_cnt) { + DPAA2_PMD_ERR("xstats id value isn't valid"); + return -EINVAL; + } + id = ids ? ids[i] : i; + if (id >= DPAA2_MAC_XSTATS_START_ID) { + if (!dpaa2_dev_mac_xstats_avail(dev)) { + values[i] = 0; + continue; + } + if (mac_fetched) { + cnt_values = priv->cnt_values_dma_mem; + values[i] = cnt_values[id - DPAA2_MAC_XSTATS_START_ID]; + continue; + } + goto dpmac_get_xstat; + } + page_id = 0; + stat_id = 0; + param = 0; + retcode = dpaa2_xstats_id_parse(id, &page_id, &stat_id, ¶m, NULL); if (retcode) - return 0; + return retcode; + if (!dpaa2_dev_dpni_xstats_avail(dev, page_id, param)) { + values[i] = 0; + continue; + } + if (!page_fetched[page_id][param]) + goto dpni_get_xstat; + values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; + continue; + +dpmac_get_xstat: + /* Single MC call fetches all MAC counters at once; + * reuse the result for every subsequent MAC xstat. + */ + retcode = dpaa2_dev_xstat_mac_setup_mem(dev); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to setup %s's MAC statistics!", + __func__, retcode, dev->data->name); + return retcode; + } + retcode = dpni_get_mac_statistics(dpni, CMD_PRI_LOW, + priv->token, priv->cnt_idx_iova, + priv->cnt_values_iova, DPAA2_MAC_NUM_STATS); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's MAC statistics!", + __func__, retcode, dev->data->name); + return retcode; + } + mac_fetched = true; + cnt_values = priv->cnt_values_dma_mem; + values[i] = cnt_values[id - DPAA2_MAC_XSTATS_START_ID]; + continue; - /* Get Counters from page_1*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 1, 0, &value[1]); - if (retcode) - return 0; +dpni_get_xstat: + /* Cache dpni page results: multiple xstats can share + * the same (page_id, param), so only fetch each pair once. + */ + retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, + priv->token, page_id, param, + &priv->pg_xstats[page_id][param]); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's statistcis of page%d!", + __func__, retcode, dev->data->name, page_id); + return retcode; + } + page_fetched[page_id][param] = true; + values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; + } - /* Get Counters from page_2*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 2, 0, &value[2]); - if (retcode) - return 0; + return n; +} - /* Get Counters from page_4*/ - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token, - 4, 0, &value[4]); - if (retcode) - return 0; +static int +dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, + const uint64_t *ids, struct rte_eth_xstat_name *xstats_names, + uint32_t limit) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + uint16_t i, stat_cnt; - for (i = 0; i < stat_cnt; i++) { - page_id = dpaa2_xstats_strings[i].page_id; - stats_id = dpaa2_xstats_strings[i].stats_id; - values[i] = value[page_id].raw.counter[stats_id]; - } - return stat_cnt; - } + stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; + if (priv->ep_dev_type == DPAA2_MAC) + stat_cnt += DPAA2_MAC_NUM_STATS; - dpaa2_xstats_get_by_id(dev, NULL, values_copy, stat_cnt); + if (!ids) + return dpaa2_dev_xstats_get_names(dev, xstats_names, limit); - for (i = 0; i < n; i++) { + for (i = 0; i < limit; i++) { if (ids[i] >= stat_cnt) { - DPAA2_PMD_ERR("xstats id value isn't valid"); + DPAA2_PMD_ERR("xstats id[%d] value(%" PRIu64 ") >= max count(%d)", + i, ids[i], stat_cnt); return -EINVAL; } - values[i] = values_copy[ids[i]]; + if (ids[i] < DPAA2_DPNI_XSTAT_MAX_NUM) { + rte_strscpy(xstats_names[i].name, dpaa2_dpni_xstats_strings[ids[i]], + RTE_ETH_XSTATS_NAME_SIZE); + } else { + rte_strscpy(xstats_names[i].name, + dpaa2_mac_xstats_strings[ids[i] - DPAA2_DPNI_XSTAT_MAX_NUM], + RTE_ETH_XSTATS_NAME_SIZE); + } } - return n; + return limit; } static int -dpaa2_xstats_get_names_by_id(struct rte_eth_dev *dev, - const uint64_t *ids, - struct rte_eth_xstat_name *xstats_names, - unsigned int limit) +dpaa2_dev_stats_get(struct rte_eth_dev *dev, + struct rte_eth_stats *stats, struct eth_queue_stats *qstats) { - unsigned int i, stat_cnt = RTE_DIM(dpaa2_xstats_strings); - struct rte_eth_xstat_name xstats_names_copy[stat_cnt]; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int32_t retcode; + uint16_t stats_len = RTE_DIM(dpaa2_stats_strings), i, j, xstats_len; + struct dpaa2_queue *dpaa2_q; + uint64_t ids[stats_len]; + uint64_t counts[stats_len]; + uint64_t ifiltered = 0; + const char **dpni_nms = (const char **)&dpaa2_dpni_xstats_strings; - if (!ids) - return dpaa2_xstats_get_names(dev, xstats_names, limit); + PMD_INIT_FUNC_TRACE(); - dpaa2_xstats_get_names(dev, xstats_names_copy, limit); + xstats_len = DPAA2_DPNI_XSTAT_MAX_NUM; + if (priv->ep_dev_type == DPAA2_MAC) + xstats_len += DPAA2_MAC_NUM_STATS; - for (i = 0; i < limit; i++) { - if (ids[i] >= stat_cnt) { - DPAA2_PMD_ERR("xstats id value isn't valid"); - return -1; + if (!stats) { + DPAA2_PMD_ERR("stats is NULL"); + return -EINVAL; + } + + memset(stats, 0, sizeof(struct rte_eth_stats)); + + for (i = 0; i < stats_len; i++) { + for (j = 0; j < xstats_len; j++) { + if (j < DPAA2_DPNI_XSTAT_MAX_NUM) { + retcode = strcmp(dpaa2_stats_strings[i].name, dpni_nms[j]); + } else { + retcode = strcmp(dpaa2_stats_strings[i].name, + dpaa2_mac_xstats_strings[j - DPAA2_DPNI_XSTAT_MAX_NUM]); + } + if (!retcode) { + ids[i] = j; + break; + } + } + if (j == xstats_len) { + DPAA2_PMD_ERR("%s: stat(%s) not found in xstat!", + __func__, dpaa2_stats_strings[i].name); + return -EINVAL; } - strcpy(xstats_names[i].name, xstats_names_copy[ids[i]].name); } - return limit; + + retcode = dpaa2_dev_xstats_get_by_id(dev, ids, counts, stats_len); + if (retcode != stats_len) { + DPAA2_PMD_ERR("%s: Failed to get xstats (%d)counters by %d IDs", + __func__, retcode, stats_len); + if (retcode >= 0) + retcode = -EINVAL; + return retcode; + } + + for (i = 0; i < stats_len; i++) { + if (dpaa2_stats_strings[i].offset < sizeof(struct rte_eth_stats)) { + DPAA2_STATS_SET_BY_OFFSET(stats, + dpaa2_stats_strings[i].offset, counts[i]); + } else { + ifiltered = counts[i]; + } + } + stats->imissed = stats->ierrors + stats->rx_nombuf + ifiltered; + + if (qstats) { + for (i = 0; i < dev->data->nb_rx_queues; i++) { + dpaa2_q = priv->rx_vq[i]; + if (dpaa2_q) + qstats[i].q_ipackets = dpaa2_q->rx_pkts; + } + for (i = 0; i < dev->data->nb_tx_queues; i++) { + dpaa2_q = priv->tx_vq[i]; + if (dpaa2_q) + qstats[i].q_opackets = dpaa2_q->tx_pkts; + } + } + + return 0; } static int @@ -3326,9 +3595,9 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .link_update = dpaa2_dev_link_update, .stats_get = dpaa2_dev_stats_get, .xstats_get = dpaa2_dev_xstats_get, - .xstats_get_by_id = dpaa2_xstats_get_by_id, - .xstats_get_names_by_id = dpaa2_xstats_get_names_by_id, - .xstats_get_names = dpaa2_xstats_get_names, + .xstats_get_by_id = dpaa2_dev_xstats_get_by_id, + .xstats_get_names_by_id = dpaa2_dev_xstats_get_names_by_id, + .xstats_get_names = dpaa2_dev_xstats_get_names, .stats_reset = dpaa2_dev_stats_reset, .xstats_reset = dpaa2_dev_stats_reset, .fw_version_get = dpaa2_fw_version_get, @@ -3682,17 +3951,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); - /* mac_statistics supported on MC version > 10.39.0 */ - { - struct mc_version mc_ver_info = {0}; - - if (!mc_get_version(dpni_dev, CMD_PRI_LOW, &mc_ver_info) && - mc_ver_info.major >= MC_VER_MAJOR && - mc_ver_info.minor >= MC_VER_MINOR && - mc_ver_info.revision > 0) - dpaa2_dev_mac_setup_stats(eth_dev); - } - return 0; init_err: dpaa2_dev_close(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index cc0292cd9c..00bbc17862 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -206,6 +206,7 @@ #define DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 106) #define DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_MAC_XSTATS_MC_REV RTE_FSL_MC_REV(10, 39, 109) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -514,6 +515,12 @@ struct dpaa2_dev_priv { uint64_t cnt_idx_iova, cnt_values_iova; uint64_t mc_rev; + /* Cache one dpni_statistics result per (page_id, param) pair to avoid + * redundant MC commands when multiple xstats share the same page. + * Put it in heap to avoid allocating multi-KB stack in runtime. + */ + union dpni_statistics pg_xstats[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; + struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; LIST_HEAD(nodes, dpaa2_tm_node) nodes; @@ -662,8 +669,4 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); - -void -dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); - #endif /* _DPAA2_ETHDEV_H */ diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index f47f383a9b..b63627493a 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -688,50 +688,77 @@ int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, * @page_6.tx_pending_frames_cnt: total number of frames pending in Tx queues * @raw: raw statistics structure, used to index counters */ +enum dpni_statistics_page_id { + DPNI_INGRESS_STATISTICS_PAGE_ID = 0, + DPNI_EGRESS_STATISTICS_PAGE_ID = 1, + DPNI_ERR_STATISTICS_PAGE_ID = 2, + DPNI_CEETM_STATISTICS_PAGE_ID = 3, + DPNI_CGR_STATISTICS_PAGE_ID = 4, + DPNI_POLICER_STATISTICS_PAGE_ID = 5, + DPNI_TX_PENDING_STATISTICS_PAGE_ID = 6, + DPNI_MAX_STATISTICS_PAGE_ID +}; + +struct dpni_statistics_page_0 { + uint64_t ingress_all_frames; + uint64_t ingress_all_bytes; + uint64_t ingress_multicast_frames; + uint64_t ingress_multicast_bytes; + uint64_t ingress_broadcast_frames; + uint64_t ingress_broadcast_bytes; +}; + +struct dpni_statistics_page_1 { + uint64_t egress_all_frames; + uint64_t egress_all_bytes; + uint64_t egress_multicast_frames; + uint64_t egress_multicast_bytes; + uint64_t egress_broadcast_frames; + uint64_t egress_broadcast_bytes; +}; + +struct dpni_statistics_page_2 { + uint64_t ingress_filtered_frames; + uint64_t ingress_discarded_frames; + uint64_t ingress_nobuffer_discards; + uint64_t egress_discarded_frames; + uint64_t egress_confirmed_frames; +}; + +struct dpni_statistics_page_3 { + uint64_t ceetm_dequeue_bytes; + uint64_t ceetm_dequeue_frames; + uint64_t ceetm_reject_bytes; + uint64_t ceetm_reject_frames; +}; + +struct dpni_statistics_page_4 { + uint64_t cgr_reject_frames; + uint64_t cgr_reject_bytes; +}; + +struct dpni_statistics_page_5 { + uint64_t policer_cnt_red; + uint64_t policer_cnt_yellow; + uint64_t policer_cnt_green; + uint64_t policer_cnt_re_red; + uint64_t policer_cnt_re_yellow; +}; + +struct dpni_statistics_page_6 { + uint64_t tx_pending_frames_cnt; +}; + +#define DPNI_STAT_MAX_PARAM DPNI_MAX_TC + union dpni_statistics { - struct { - uint64_t ingress_all_frames; - uint64_t ingress_all_bytes; - uint64_t ingress_multicast_frames; - uint64_t ingress_multicast_bytes; - uint64_t ingress_broadcast_frames; - uint64_t ingress_broadcast_bytes; - } page_0; - struct { - uint64_t egress_all_frames; - uint64_t egress_all_bytes; - uint64_t egress_multicast_frames; - uint64_t egress_multicast_bytes; - uint64_t egress_broadcast_frames; - uint64_t egress_broadcast_bytes; - } page_1; - struct { - uint64_t ingress_filtered_frames; - uint64_t ingress_discarded_frames; - uint64_t ingress_nobuffer_discards; - uint64_t egress_discarded_frames; - uint64_t egress_confirmed_frames; - } page_2; - struct { - uint64_t ceetm_dequeue_bytes; - uint64_t ceetm_dequeue_frames; - uint64_t ceetm_reject_bytes; - uint64_t ceetm_reject_frames; - } page_3; - struct { - uint64_t cgr_reject_frames; - uint64_t cgr_reject_bytes; - } page_4; - struct { - uint64_t policer_cnt_red; - uint64_t policer_cnt_yellow; - uint64_t policer_cnt_green; - uint64_t policer_cnt_re_red; - uint64_t policer_cnt_re_yellow; - } page_5; - struct { - uint64_t tx_pending_frames_cnt; - } page_6; + struct dpni_statistics_page_0 page_0; + struct dpni_statistics_page_1 page_1; + struct dpni_statistics_page_2 page_2; + struct dpni_statistics_page_3 page_3; + struct dpni_statistics_page_4 page_4; + struct dpni_statistics_page_5 page_5; + struct dpni_statistics_page_6 page_6; struct { uint64_t counter[DPNI_STATISTICS_CNT]; } raw; @@ -2134,9 +2161,6 @@ int dpni_sp_enable(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, int dpni_get_mac_statistics(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint64_t iova_cnt, uint64_t iova_values, uint32_t num_cnt); -int dpni_get_mac_statistics(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, - uint64_t iova_cnt, uint64_t iova_values, uint32_t num_cnt); - int dpni_get_mac_speed_capability(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint32_t *speed_cap); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 18/65] net/dpaa2: unify xstats layout and add DPMAC counter struct 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (16 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 17/65] net/dpaa2: rework xstats with page table and MAC support Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 19/65] net/dpaa2: reimplement xstats_get() on top of xstats_get_by_id() Prashant Gupta ` (46 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPNI page counters and the DPMAC counters were described by three loosely coupled artifacts: a struct dpaa2_dpni_xstats_pg_seq covering only the DPNI pages, a parallel s_dpaa2_dpni_xstats_pgs[] descriptor table carrying (page_offset, page_id, param, size), and two separate name arrays (dpaa2_dpni_xstats_strings[] and dpaa2_mac_xstats_strings[]). Keeping those three in sync was manual and error prone, and dpaa2_dev_stats_get() further depended on a fourth table (dpaa2_stats_strings[]) plus a string-match loop to translate rte_eth_stats fields into xstat ids. Collapse all of this to a single source of truth driven by the C struct layout. Behavior is unchanged apart from the per-TC policer name format; the refactor removes ~200 lines of duplicated metadata and makes adding a new counter a one-line struct change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 549 +++++++++++++------------------ drivers/net/dpaa2/dpaa2_ethdev.h | 3 +- drivers/net/dpaa2/mc/fsl_dpni.h | 146 ++++++++ 3 files changed, 378 insertions(+), 320 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index e7ac6b7dad..b30a8e7b3d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -169,7 +169,7 @@ dpaa2_dist_size_is_supported(uint16_t n) int dpaa2_valid_dev; struct rte_mempool *dpaa2_tx_sg_pool; -struct dpaa2_dpni_xstats_pg_seq { +struct dpaa2_xstats_seq { struct dpni_statistics_page_0 pg0; struct dpni_statistics_page_1 pg1; struct dpni_statistics_page_2 pg2; @@ -177,119 +177,81 @@ struct dpaa2_dpni_xstats_pg_seq { struct dpni_statistics_page_4 pg4; struct dpni_statistics_page_5 pg5[MAX_TCS]; struct dpni_statistics_page_6 pg6; + struct dpni_dpmac_counters mac_cnt; }; #define DPAA2_DPNI_XSTAT_MAX_NUM \ - (sizeof(struct dpaa2_dpni_xstats_pg_seq) / sizeof(uint64_t)) - -struct dpaa2_dpni_xstats_pg { - uint64_t page_offset; - enum dpni_statistics_page_id page_id; - uint16_t param; - uint16_t size; -}; - -static const struct dpaa2_dpni_xstats_pg s_dpaa2_dpni_xstats_pgs[] = { - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg0), - DPNI_INGRESS_STATISTICS_PAGE_ID, 0, - sizeof(struct dpni_statistics_page_0) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg1), - DPNI_EGRESS_STATISTICS_PAGE_ID, 0, - sizeof(struct dpni_statistics_page_1) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg2), - DPNI_ERR_STATISTICS_PAGE_ID, 0, - sizeof(struct dpni_statistics_page_2) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg3), - DPNI_CEETM_STATISTICS_PAGE_ID, 0, - sizeof(struct dpni_statistics_page_3) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg4), - DPNI_CGR_STATISTICS_PAGE_ID, 0, - sizeof(struct dpni_statistics_page_4) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[0]), - DPNI_POLICER_STATISTICS_PAGE_ID, 0, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[1]), - DPNI_POLICER_STATISTICS_PAGE_ID, 1, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[2]), - DPNI_POLICER_STATISTICS_PAGE_ID, 2, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[3]), - DPNI_POLICER_STATISTICS_PAGE_ID, 3, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[4]), - DPNI_POLICER_STATISTICS_PAGE_ID, 4, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[5]), - DPNI_POLICER_STATISTICS_PAGE_ID, 5, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[6]), - DPNI_POLICER_STATISTICS_PAGE_ID, 6, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg5[7]), - DPNI_POLICER_STATISTICS_PAGE_ID, 7, - sizeof(struct dpni_statistics_page_5) - }, - { - offsetof(struct dpaa2_dpni_xstats_pg_seq, pg6), - DPNI_TX_PENDING_STATISTICS_PAGE_ID, 0, - sizeof(struct dpni_statistics_page_6) - }, - { - sizeof(struct dpaa2_dpni_xstats_pg_seq), - 0, 0, 0 - } -}; + (offsetof(struct dpaa2_xstats_seq, mac_cnt) / sizeof(uint64_t)) + +#define DPAA2_DPNI_STAT_SET_PAGE_PARAM(param) \ +({ \ + int ret = false; \ + \ + if ((id) >= this_offset && (id) < (this_offset + pg_size)) { \ + _stat_id = (id) - this_offset; \ + _param = param; \ + _size = pg_size; \ + ret = true; \ + } \ + ret; \ +}) + +#define DPAA2_DPNI_STAT_PAGE_PARAM(pid) \ +({ \ + uint64_t this_offset = offsetof(struct dpaa2_xstats_seq, pg##pid) / sizeof(uint64_t); \ + uint64_t pg_size = sizeof(struct dpni_statistics_page_##pid) / sizeof(uint64_t); \ + int ret; \ + \ + ret = DPAA2_DPNI_STAT_SET_PAGE_PARAM(0); \ + if (!ret) \ + _page++; \ + ret; \ +}) + +#define DPAA2_DPNI_STAT_POLICER_PAGE_PARAM() \ +({ \ + int ret = false; \ + uint8_t tc_id; \ + uint64_t this_offset; \ + uint64_t pg_size = sizeof(struct dpni_statistics_page_5) / sizeof(uint64_t); \ + \ + for (tc_id = 0; tc_id < MAX_TCS; tc_id++) { \ + this_offset = offsetof(struct dpaa2_xstats_seq, pg5[tc_id]) / sizeof(uint64_t); \ + ret = DPAA2_DPNI_STAT_SET_PAGE_PARAM(tc_id); \ + if (ret) \ + break; \ + } \ + if (!ret) \ + _page++; \ + ret; \ +}) static inline int dpaa2_xstats_id_parse(uint32_t id, uint8_t *page, uint8_t *stat_id, uint16_t *param, uint16_t *size) { - int found = 0; - uint8_t _page = 0, _stat_id = 0; + uint8_t _page = DPNI_INGRESS_STATISTICS_PAGE_ID, _stat_id = 0; uint16_t _param = 0, _size = 0; - uint64_t offset = id * sizeof(uint64_t), page_offset = 0, i; - - for (i = 1; i < RTE_DIM(s_dpaa2_dpni_xstats_pgs); i++) { - if (offset < s_dpaa2_dpni_xstats_pgs[i].page_offset) { - page_offset = s_dpaa2_dpni_xstats_pgs[i - 1].page_offset; - _page = s_dpaa2_dpni_xstats_pgs[i - 1].page_id; - _stat_id = (offset - page_offset) / sizeof(uint64_t); - _param = s_dpaa2_dpni_xstats_pgs[i - 1].param; - _size = s_dpaa2_dpni_xstats_pgs[i - 1].size / sizeof(uint64_t); - found = 1; - break; - } - } - - if (!found) - return -EINVAL; + if (DPAA2_DPNI_STAT_PAGE_PARAM(0)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(1)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(2)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(3)) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(4)) + goto found_id; + if (DPAA2_DPNI_STAT_POLICER_PAGE_PARAM()) + goto found_id; + if (DPAA2_DPNI_STAT_PAGE_PARAM(6)) + goto found_id; + + DPAA2_PMD_ERR("ID(%d) was not found in DPNI page statistics", id); + return -EINVAL; + +found_id: if (page) *page = _page; if (stat_id) @@ -302,156 +264,155 @@ dpaa2_xstats_id_parse(uint32_t id, uint8_t *page, return 0; } -struct dpaa2_stats_name_off { - char name[RTE_ETH_XSTATS_NAME_SIZE]; - uint64_t offset; +#define DPAA2_XSTAT_STR_SET(pg, field) \ + .pg.field = (uint64_t)RTE_STR(field) + +#define DPAA2_XSTAT_TC_STR_SET(pg, tc, field) \ + .pg[tc].field = (uint64_t)("TC" RTE_STR(tc)"_" RTE_STR(field)) + +#define DPAA2_XSTAT_TC_COLOR_STR_SET(pg, tc) \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_red), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_yellow), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_green), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_re_red), \ + DPAA2_XSTAT_TC_STR_SET(pg, tc, policer_cnt_re_yellow) + +#define MAC_STR(name) ("mac_" #name) +#define MAC_STR_ADDR(name) ((size_t)MAC_STR(name)) + +static const struct dpaa2_xstats_seq dpaa2_xstats_strings = { + DPAA2_XSTAT_STR_SET(pg0, ingress_all_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_all_bytes), + DPAA2_XSTAT_STR_SET(pg0, ingress_multicast_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_multicast_bytes), + DPAA2_XSTAT_STR_SET(pg0, ingress_broadcast_frames), + DPAA2_XSTAT_STR_SET(pg0, ingress_broadcast_bytes), + + DPAA2_XSTAT_STR_SET(pg1, egress_all_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_all_bytes), + DPAA2_XSTAT_STR_SET(pg1, egress_multicast_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_multicast_bytes), + DPAA2_XSTAT_STR_SET(pg1, egress_broadcast_frames), + DPAA2_XSTAT_STR_SET(pg1, egress_broadcast_bytes), + + DPAA2_XSTAT_STR_SET(pg2, ingress_filtered_frames), + DPAA2_XSTAT_STR_SET(pg2, ingress_discarded_frames), + DPAA2_XSTAT_STR_SET(pg2, ingress_nobuffer_discards), + DPAA2_XSTAT_STR_SET(pg2, egress_discarded_frames), + DPAA2_XSTAT_STR_SET(pg2, egress_confirmed_frames), + + DPAA2_XSTAT_STR_SET(pg3, ceetm_dequeue_bytes), + DPAA2_XSTAT_STR_SET(pg3, ceetm_dequeue_frames), + DPAA2_XSTAT_STR_SET(pg3, ceetm_reject_bytes), + DPAA2_XSTAT_STR_SET(pg3, ceetm_reject_frames), + + DPAA2_XSTAT_STR_SET(pg4, cgr_reject_frames), + DPAA2_XSTAT_STR_SET(pg4, cgr_reject_bytes), + + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 0), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 1), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 2), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 3), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 4), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 5), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 6), + DPAA2_XSTAT_TC_COLOR_STR_SET(pg5, 7), + + DPAA2_XSTAT_STR_SET(pg6, tx_pending_frames_cnt), + + .mac_cnt.rx_64_bytes = MAC_STR_ADDR(rx_64_bytes), + .mac_cnt.rx_65_127_bytes = MAC_STR_ADDR(rx_65_127_bytes), + .mac_cnt.rx_128_255_bytes = MAC_STR_ADDR(rx_128_255_bytes), + .mac_cnt.rx_256_511_bytes = MAC_STR_ADDR(rx_256_511_bytes), + .mac_cnt.rx_512_1023_bytes = MAC_STR_ADDR(rx_512_1023_bytes), + .mac_cnt.rx_1024_1518_bytes = MAC_STR_ADDR(rx_1024_1518_bytes), + .mac_cnt.rx_1519_max_bytes = MAC_STR_ADDR(rx_1519_max_bytes), + + .mac_cnt.rx_fragments = MAC_STR_ADDR(rx_fragments), + .mac_cnt.rx_jabber = MAC_STR_ADDR(rx_jabber), + .mac_cnt.rx_drop_fifo = MAC_STR_ADDR(rx_drop_fifo), + .mac_cnt.rx_alignment_error = MAC_STR_ADDR(rx_alignment_error), + + .mac_cnt.tx_undersize_good = MAC_STR_ADDR(tx_undersize_good), + .mac_cnt.rx_oversize_good = MAC_STR_ADDR(rx_oversize_good), + + .mac_cnt.rx_pause = MAC_STR_ADDR(rx_pause), + .mac_cnt.tx_pause = MAC_STR_ADDR(tx_pause), + + .mac_cnt.rx_good_bytes = MAC_STR_ADDR(rx_good_bytes), + .mac_cnt.rx_multicast = MAC_STR_ADDR(rx_multicast), + .mac_cnt.rx_broadcast = MAC_STR_ADDR(rx_broadcast), + .mac_cnt.rx_all_frames = MAC_STR_ADDR(rx_all_frames), + .mac_cnt.rx_unicast = MAC_STR_ADDR(rx_unicast), + .mac_cnt.rx_error = MAC_STR_ADDR(rx_error), + + .mac_cnt.tx_good_bytes = MAC_STR_ADDR(tx_good_bytes), + .mac_cnt.tx_multicast = MAC_STR_ADDR(tx_multicast), + .mac_cnt.tx_broadcast = MAC_STR_ADDR(tx_broadcast), + .mac_cnt.tx_unicast = MAC_STR_ADDR(tx_unicast), + .mac_cnt.tx_error = MAC_STR_ADDR(tx_error), + + .mac_cnt.rx_valid_frames = MAC_STR_ADDR(rx_valid_frames), + .mac_cnt.tx_valid_frames = MAC_STR_ADDR(tx_valid_frames), + + .mac_cnt.tx_64_bytes = MAC_STR_ADDR(tx_64_bytes), + .mac_cnt.tx_65_127_bytes = MAC_STR_ADDR(tx_65_127_bytes), + .mac_cnt.tx_128_255_bytes = MAC_STR_ADDR(tx_128_255_bytes), + .mac_cnt.tx_256_511_bytes = MAC_STR_ADDR(tx_256_511_bytes), + .mac_cnt.tx_512_1023_bytes = MAC_STR_ADDR(tx_512_1023_bytes), + .mac_cnt.tx_1024_1518_bytes = MAC_STR_ADDR(tx_1024_1518_bytes), + .mac_cnt.tx_1519_max_bytes = MAC_STR_ADDR(tx_1519_max_bytes), + + .mac_cnt.rx_bytes_all = MAC_STR_ADDR(rx_bytes_all), + .mac_cnt.rx_crc_error = MAC_STR_ADDR(rx_crc_error), + .mac_cnt.rx_vlan = MAC_STR_ADDR(rx_vlan), + .mac_cnt.rx_undersize_good = MAC_STR_ADDR(rx_undersize_good), + .mac_cnt.rx_ctrl_non_pause = MAC_STR_ADDR(rx_ctrl_non_pause), + .mac_cnt.rx_drop_full = MAC_STR_ADDR(rx_drop_full), + + .mac_cnt.tx_bytes_all = MAC_STR_ADDR(tx_bytes_all), + .mac_cnt.tx_crc_error = MAC_STR_ADDR(tx_crc_error), + .mac_cnt.tx_vlan = MAC_STR_ADDR(tx_vlan), + .mac_cnt.tx_all_frames = MAC_STR_ADDR(tx_all_frames), + .mac_cnt.tx_ctrl_non_pause = MAC_STR_ADDR(tx_ctrl_non_pause), + + .mac_cnt.rx_pfc_class[0] = MAC_STR_ADDR(rx_pfc_class_0), + .mac_cnt.rx_pfc_class[1] = MAC_STR_ADDR(rx_pfc_class_1), + .mac_cnt.rx_pfc_class[2] = MAC_STR_ADDR(rx_pfc_class_2), + .mac_cnt.rx_pfc_class[3] = MAC_STR_ADDR(rx_pfc_class_3), + .mac_cnt.rx_pfc_class[4] = MAC_STR_ADDR(rx_pfc_class_4), + .mac_cnt.rx_pfc_class[5] = MAC_STR_ADDR(rx_pfc_class_5), + .mac_cnt.rx_pfc_class[6] = MAC_STR_ADDR(rx_pfc_class_6), + .mac_cnt.rx_pfc_class[7] = MAC_STR_ADDR(rx_pfc_class_7), + + .mac_cnt.tx_pfc_class[0] = MAC_STR_ADDR(tx_pfc_class_0), + .mac_cnt.tx_pfc_class[1] = MAC_STR_ADDR(tx_pfc_class_1), + .mac_cnt.tx_pfc_class[2] = MAC_STR_ADDR(tx_pfc_class_2), + .mac_cnt.tx_pfc_class[3] = MAC_STR_ADDR(tx_pfc_class_3), + .mac_cnt.tx_pfc_class[4] = MAC_STR_ADDR(tx_pfc_class_4), + .mac_cnt.tx_pfc_class[5] = MAC_STR_ADDR(tx_pfc_class_5), + .mac_cnt.tx_pfc_class[6] = MAC_STR_ADDR(tx_pfc_class_6), + .mac_cnt.tx_pfc_class[7] = MAC_STR_ADDR(tx_pfc_class_7) }; -#define DPAA2_STATS_IPACKETS_STR "ingress_all_frames" -#define DPAA2_STATS_OPACKETS_STR "egress_all_frames" -#define DPAA2_STATS_IBYTES_STR "ingress_all_bytes" -#define DPAA2_STATS_OBYTES_STR "egress_all_bytes" -#define DPAA2_STATS_IERRORS_STR "ingress_discarded_frames" -#define DPAA2_STATS_OERRORS_STR "egress_discarded_frames" -#define DPAA2_STATS_RX_NOMBUF_STR "ingress_nobuffer_discards" -#define DPAA2_STATS_FILTERED_STR "ingress_filtered_frames" - -static const struct dpaa2_stats_name_off dpaa2_stats_strings[] = { - { - DPAA2_STATS_IPACKETS_STR, - offsetof(struct rte_eth_stats, ipackets) - }, - { - DPAA2_STATS_OPACKETS_STR, - offsetof(struct rte_eth_stats, opackets) - }, - { - DPAA2_STATS_IBYTES_STR, - offsetof(struct rte_eth_stats, ibytes) - }, - { - DPAA2_STATS_OBYTES_STR, - offsetof(struct rte_eth_stats, obytes) - }, - { - DPAA2_STATS_FILTERED_STR, - sizeof(struct rte_eth_stats) - }, - { - DPAA2_STATS_IERRORS_STR, - offsetof(struct rte_eth_stats, ierrors) - }, - { - DPAA2_STATS_OERRORS_STR, - offsetof(struct rte_eth_stats, oerrors) - }, - { - DPAA2_STATS_RX_NOMBUF_STR, - offsetof(struct rte_eth_stats, rx_nombuf) - } +#define DPAA2_DPNI_XSTAT_FIELD_ID(field) \ + (offsetof(struct dpaa2_xstats_seq, field) / sizeof(uint64_t)) + +static const struct rte_eth_stats dpaa2_stats_xstat_ids = { + .ipackets = DPAA2_DPNI_XSTAT_FIELD_ID(pg0.ingress_all_frames), + .opackets = DPAA2_DPNI_XSTAT_FIELD_ID(pg1.egress_all_frames), + .ibytes = DPAA2_DPNI_XSTAT_FIELD_ID(pg0.ingress_all_bytes), + .obytes = DPAA2_DPNI_XSTAT_FIELD_ID(pg1.egress_all_bytes), + .imissed = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_filtered_frames), + .ierrors = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_discarded_frames), + .oerrors = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.egress_discarded_frames), + .rx_nombuf = DPAA2_DPNI_XSTAT_FIELD_ID(pg2.ingress_nobuffer_discards) }; -#define DPAA2_STATS_SET_BY_OFFSET(p_stats, offset, val) \ - (*((uint64_t *)((uint8_t *)(p_stats) + (offset))) = (val)) - -#define DPAA2_TC_COLOR(tc) \ - "TC_"#tc"_policer_cnt_red", \ - "TC_"#tc"_policer_cnt_yellow", \ - "TC_"#tc"_policer_cnt_green", \ - "TC_"#tc"_policer_cnt_re_red", \ - "TC_"#tc"_policer_cnt_re_yellow" \ - -static const char * const dpaa2_dpni_xstats_strings[] = { - DPAA2_STATS_IPACKETS_STR, - DPAA2_STATS_IBYTES_STR, - "ingress_multicast_frames", - "ingress_multicast_bytes", - "ingress_broadcast_frames", - "ingress_broadcast_bytes", - - DPAA2_STATS_OPACKETS_STR, - DPAA2_STATS_OBYTES_STR, - "egress_multicast_frames", - "egress_multicast_bytes", - "egress_broadcast_frames", - "egress_broadcast_bytes", - - DPAA2_STATS_FILTERED_STR, - DPAA2_STATS_IERRORS_STR, - DPAA2_STATS_RX_NOMBUF_STR, - DPAA2_STATS_OERRORS_STR, - "egress_confirmed_frames", - - "cgr_reject_frames", - "cgr_reject_bytes", - - "ceetm_dequeue_bytes", - "ceetm_dequeue_frames", - "ceetm_reject_bytes", - "ceetm_reject_frames", - DPAA2_TC_COLOR(0), - DPAA2_TC_COLOR(1), - DPAA2_TC_COLOR(2), - DPAA2_TC_COLOR(3), - DPAA2_TC_COLOR(4), - DPAA2_TC_COLOR(5), - DPAA2_TC_COLOR(6), - DPAA2_TC_COLOR(7), - - "tx_pending_frames_cnt" -}; +#define DPAA2_STATS_XSTATS_NUM \ + (sizeof(dpaa2_stats_xstat_ids) / sizeof(uint64_t)) -static const char * const dpaa2_mac_xstats_strings[] = { - "mac_rx_64 bytes", - "mac_rx_65-127 bytes", - "mac_rx_128-255 bytes", - "mac_rx_256-511 bytes", - "mac_rx_512-1023 bytes", - "mac_rx_1024-1518 bytes", - "mac_rx_1519-max bytes", - "mac_rx_frags", - "mac_rx_jabber", - "mac_rx_frame discards", - "mac_rx_align errors", - "mac_tx_undersized", - "mac_rx_oversized", - "mac_rx_pause", - "mac_tx_b-pause", - "mac_rx_bytes", - "mac_rx_m-cast", - "mac_rx_b-cast", - "mac_rx_all frames", - "mac_rx_u-cast", - "mac_rx_frame errors", - "mac_tx_bytes", - "mac_tx_m-cast", - "mac_tx_b-cast", - "mac_tx_u-cast", - "mac_tx_frame errors", - "mac_rx_frames ok", - "mac_tx_frames ok", - "mac_tx_64 bytes", - "mac_tx_65-127 bytes", - "mac_tx_128-255 bytes", - "mac_tx_256-511 bytes", - "mac_tx_512-1023 bytes", - "mac_tx_1024-1518 bytes", - "mac_tx_1519-max bytes", - "mac_rx_all_bytes", - "mac_rx_fcs_err", - "mac_rx_vlan_frame", - "mac_rx_undersized", - "mac_rx_control_frame", - "mac_rx_frame_discard_not_trunc", - "mac_tx_all_bytes", - "mac_tx_fcs_err", - "mac_tx_vlan_frame", - "mac_tx_all_frame", - "mac_tx_control_frame" -}; - -#define DPAA2_MAC_XSTATS_START_ID \ - (sizeof(struct dpaa2_dpni_xstats_pg_seq) / sizeof(uint64_t)) +#define DPAA2_MAC_XSTATS_START_ID DPAA2_DPNI_XSTAT_MAX_NUM static struct rte_dpaa2_driver rte_dpaa2_pmd; static int dpaa2_dev_link_update(struct rte_eth_dev *dev, @@ -2333,6 +2294,7 @@ dpaa2_dev_xstats_get_names(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; uint16_t i, stat_cnt; + uint64_t xstat_str[sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)]; stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; if (priv->ep_dev_type == DPAA2_MAC) @@ -2347,16 +2309,10 @@ dpaa2_dev_xstats_get_names(struct rte_eth_dev *dev, if (!xstats_names) return stat_cnt; - for (i = 0; i < stat_cnt; i++) { - if (i < DPAA2_DPNI_XSTAT_MAX_NUM) { - rte_strscpy(xstats_names[i].name, dpaa2_dpni_xstats_strings[i], - RTE_ETH_XSTATS_NAME_SIZE); - } else { - rte_strscpy(xstats_names[i].name, - dpaa2_mac_xstats_strings[i - DPAA2_DPNI_XSTAT_MAX_NUM], - RTE_ETH_XSTATS_NAME_SIZE); - } - } + rte_memcpy(xstat_str, &dpaa2_xstats_strings, sizeof(xstat_str)); + + for (i = 0; i < stat_cnt; i++) + rte_strscpy(xstats_names[i].name, (char *)xstat_str[i], RTE_ETH_XSTATS_NAME_SIZE); return stat_cnt; } @@ -2464,6 +2420,7 @@ dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; uint16_t i, stat_cnt; + uint64_t xstat_str[sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)]; stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; if (priv->ep_dev_type == DPAA2_MAC) @@ -2472,20 +2429,15 @@ dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, if (!ids) return dpaa2_dev_xstats_get_names(dev, xstats_names, limit); + rte_memcpy(xstat_str, &dpaa2_xstats_strings, sizeof(xstat_str)); + for (i = 0; i < limit; i++) { if (ids[i] >= stat_cnt) { DPAA2_PMD_ERR("xstats id[%d] value(%" PRIu64 ") >= max count(%d)", i, ids[i], stat_cnt); return -EINVAL; } - if (ids[i] < DPAA2_DPNI_XSTAT_MAX_NUM) { - rte_strscpy(xstats_names[i].name, dpaa2_dpni_xstats_strings[ids[i]], - RTE_ETH_XSTATS_NAME_SIZE); - } else { - rte_strscpy(xstats_names[i].name, - dpaa2_mac_xstats_strings[ids[i] - DPAA2_DPNI_XSTAT_MAX_NUM], - RTE_ETH_XSTATS_NAME_SIZE); - } + rte_strscpy(xstats_names[i].name, (char *)xstat_str[ids[i]], RTE_ETH_XSTATS_NAME_SIZE); } return limit; } @@ -2496,64 +2448,24 @@ dpaa2_dev_stats_get(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; int32_t retcode; - uint16_t stats_len = RTE_DIM(dpaa2_stats_strings), i, j, xstats_len; + uint16_t i; + uint64_t ids[DPAA2_STATS_XSTATS_NUM], counts[DPAA2_STATS_XSTATS_NUM] = {0}; struct dpaa2_queue *dpaa2_q; - uint64_t ids[stats_len]; - uint64_t counts[stats_len]; - uint64_t ifiltered = 0; - const char **dpni_nms = (const char **)&dpaa2_dpni_xstats_strings; PMD_INIT_FUNC_TRACE(); - xstats_len = DPAA2_DPNI_XSTAT_MAX_NUM; - if (priv->ep_dev_type == DPAA2_MAC) - xstats_len += DPAA2_MAC_NUM_STATS; - - if (!stats) { - DPAA2_PMD_ERR("stats is NULL"); - return -EINVAL; - } - - memset(stats, 0, sizeof(struct rte_eth_stats)); - - for (i = 0; i < stats_len; i++) { - for (j = 0; j < xstats_len; j++) { - if (j < DPAA2_DPNI_XSTAT_MAX_NUM) { - retcode = strcmp(dpaa2_stats_strings[i].name, dpni_nms[j]); - } else { - retcode = strcmp(dpaa2_stats_strings[i].name, - dpaa2_mac_xstats_strings[j - DPAA2_DPNI_XSTAT_MAX_NUM]); - } - if (!retcode) { - ids[i] = j; - break; - } - } - if (j == xstats_len) { - DPAA2_PMD_ERR("%s: stat(%s) not found in xstat!", - __func__, dpaa2_stats_strings[i].name); - return -EINVAL; - } - } - - retcode = dpaa2_dev_xstats_get_by_id(dev, ids, counts, stats_len); - if (retcode != stats_len) { - DPAA2_PMD_ERR("%s: Failed to get xstats (%d)counters by %d IDs", - __func__, retcode, stats_len); + rte_memcpy(ids, &dpaa2_stats_xstat_ids, sizeof(dpaa2_stats_xstat_ids)); + retcode = dpaa2_dev_xstats_get_by_id(dev, ids, counts, DPAA2_STATS_XSTATS_NUM); + if (retcode != RTE_DIM(ids)) { + DPAA2_PMD_ERR("%s: Failed to get xstats (%d)counters by %ld IDs", + __func__, retcode, DPAA2_STATS_XSTATS_NUM); if (retcode >= 0) retcode = -EINVAL; return retcode; } - for (i = 0; i < stats_len; i++) { - if (dpaa2_stats_strings[i].offset < sizeof(struct rte_eth_stats)) { - DPAA2_STATS_SET_BY_OFFSET(stats, - dpaa2_stats_strings[i].offset, counts[i]); - } else { - ifiltered = counts[i]; - } - } - stats->imissed = stats->ierrors + stats->rx_nombuf + ifiltered; + rte_memcpy(stats, counts, sizeof(struct rte_eth_stats)); + stats->imissed += stats->ierrors + stats->rx_nombuf; if (qstats) { for (i = 0; i < dev->data->nb_rx_queues; i++) { @@ -2576,8 +2488,7 @@ dpaa2_dev_stats_reset(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = dev->process_private; - int retcode; - int i; + int retcode, i; struct dpaa2_queue *dpaa2_q; PMD_INIT_FUNC_TRACE(); @@ -2587,7 +2498,7 @@ dpaa2_dev_stats_reset(struct rte_eth_dev *dev) return -EINVAL; } - retcode = dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token); + retcode = dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token); if (retcode) goto error; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 00bbc17862..e2d9d5de36 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -209,7 +209,8 @@ #define DPAA2_MAC_XSTATS_MC_REV RTE_FSL_MC_REV(10, 39, 109) /* mac counters */ -#define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) +#define DPAA2_MAC_NUM_STATS \ + (sizeof(struct dpni_dpmac_counters) / sizeof(uint64_t)) #define DPAA2_MAC_STATS_INDEX_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint32_t)) #define DPAA2_MAC_STATS_VALUE_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint64_t)) diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index b63627493a..4bec348545 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -2158,6 +2158,152 @@ int dpni_set_sp_profile(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t to int dpni_sp_enable(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t type, uint8_t en); +struct dpni_dpmac_counters { + /** 0x00: Counts received 64-bytes frames, good or bad */ + uint64_t rx_64_bytes; + + /** 0x01: Counts received 65- to 127-bytes frames, good or bad */ + uint64_t rx_65_127_bytes; + + /** 0x02: Counts received 128- to 255-bytes frames, good or bad */ + uint64_t rx_128_255_bytes; + + /** 0x03: Counts received 256- to 511-bytes frames, good or bad */ + uint64_t rx_256_511_bytes; + + /** 0x04: Counts received 512- to 1023-bytes frames, good or bad */ + uint64_t rx_512_1023_bytes; + + /** 0x05: Counts received 1024- to 1518-bytes frames, good or bad */ + uint64_t rx_1024_1518_bytes; + + /** 0x06: Counts received frames >=1519 bytes */ + uint64_t rx_1519_max_bytes; + + /** 0x07: <64B frames with bad CRC */ + uint64_t rx_fragments; + + /** 0x08: >max length frames with bad FCS */ + uint64_t rx_jabber; + + /** 0x09: FIFO overflow drops (including truncated frames) */ + uint64_t rx_drop_fifo; + + /** 0x0A: Alignment error frames */ + uint64_t rx_alignment_error; + + /** 0x0B: TX <64B frames with good CRC */ + uint64_t tx_undersize_good; + + /** 0x0C: >max length frames with good FCS */ + uint64_t rx_oversize_good; + + /** 0x0D: Received pause frames (including PFC) */ + uint64_t rx_pause; + + /** 0x0E: Transmitted pause frames (including PFC) */ + uint64_t tx_pause; + + /** 0x0F: Received bytes (valid frames, exclude preamble) */ + uint64_t rx_good_bytes; + + /** 0x10: Received multicast frames */ + uint64_t rx_multicast; + + /** 0x11: Received broadcast frames */ + uint64_t rx_broadcast; + + /** 0x12: Received frames (good + bad) */ + uint64_t rx_all_frames; + + /** 0x13: Received unicast frames */ + uint64_t rx_unicast; + + /** 0x14: Received error frames (excluding fragments) */ + uint64_t rx_error; + + /** 0x15: Transmitted bytes (valid frames) */ + uint64_t tx_good_bytes; + + /** 0x16: Transmitted multicast frames */ + uint64_t tx_multicast; + + /** 0x17: Transmitted broadcast frames */ + uint64_t tx_broadcast; + + /** 0x18: Transmitted unicast frames */ + uint64_t tx_unicast; + + /** 0x19: Transmitted error frames */ + uint64_t tx_error; + + /** 0x1A: Received valid frames (no error) */ + uint64_t rx_valid_frames; + + /** 0x1B: Transmitted valid frames (no error) */ + uint64_t tx_valid_frames; + + /** 0x1C: TX 64-byte frames */ + uint64_t tx_64_bytes; + + /** 0x1D: TX 65-127-byte frames */ + uint64_t tx_65_127_bytes; + + /** 0x1E: TX 128-255-byte frames */ + uint64_t tx_128_255_bytes; + + /** 0x1F: TX 256-511-byte frames */ + uint64_t tx_256_511_bytes; + + /** 0x20: TX 512-1023-byte frames */ + uint64_t tx_512_1023_bytes; + + /** 0x21: TX 1024-1518-byte frames */ + uint64_t tx_1024_1518_bytes; + + /** 0x22: TX >=1519-byte frames */ + uint64_t tx_1519_max_bytes; + + /** 0x23: RX bytes (good + bad frames) */ + uint64_t rx_bytes_all; + + /** 0x24: RX CRC-32 error frames */ + uint64_t rx_crc_error; + + /** 0x25: Valid VLAN-tagged RX frames */ + uint64_t rx_vlan; + + /** 0x26: RX <64B frames with good CRC */ + uint64_t rx_undersize_good; + + /** 0x27: RX control frames (0x8808, non-pause) */ + uint64_t rx_ctrl_non_pause; + + /** 0x28: Fully dropped frames due to MAC client FIFO overflow */ + uint64_t rx_drop_full; + + /** 0x29: TX bytes (good + bad frames) */ + uint64_t tx_bytes_all; + + /** 0x2A: TX CRC-32 error frames */ + uint64_t tx_crc_error; + + /** 0x2B: Valid VLAN-tagged TX frames */ + uint64_t tx_vlan; + + /** 0x2C: All TX frames (good + bad) */ + uint64_t tx_all_frames; + + /** 0x2D: TX control frames (0x8808, non-pause) */ + uint64_t tx_ctrl_non_pause; + + /** 0x2E-0x35: RX PFC frames per priority (0-7) */ + uint64_t rx_pfc_class[DPNI_MAX_TC]; + + /** 0x36-0x3D: TX PFC frames per priority (0-7) */ + uint64_t tx_pfc_class[DPNI_MAX_TC]; +}; + int dpni_get_mac_statistics(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint64_t iova_cnt, uint64_t iova_values, uint32_t num_cnt); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 19/65] net/dpaa2: reimplement xstats_get() on top of xstats_get_by_id() 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (17 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 18/65] net/dpaa2: unify xstats layout and add DPMAC counter struct Prashant Gupta @ 2026-10-23 13:42 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 20/65] net/dpaa2: fetch only requested MAC xstats in one MC call Prashant Gupta ` (45 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:42 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> dpaa2_dev_xstats_get() duplicated almost all of the logic already present in dpaa2_dev_xstats_get_by_id(): it walked the DPNI pages one by one with dpaa2_xstats_id_parse(), called dpni_get_statistics() per page, special-cased the DPMAC counter range with its own dpni_get_mac_statistics() path, handled per-page/per-MAC availability with inline zero-fill loops, etc. All of that behavior is already provided by dpaa2_dev_xstats_get_by_id(), so the standalone implementation was just a second place to keep in sync. Rewrite dpaa2_dev_xstats_get() as a thin wrapper: - Clamp the requested count to DPAA2_XSTAT_MAX_NUM (new helper defined as sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)) with a warning when the caller asks for more. - Build a trivial [0..n) id array, pre-zero the xstats[] entries, and call dpaa2_dev_xstats_get_by_id() once. - Copy the returned values into xstats[].value and return the number of entries dpaa2_dev_xstats_get_by_id() produced. Also reuse DPAA2_XSTAT_MAX_NUM in dpaa2_dev_xstats_get_names() and dpaa2_dev_xstats_get_names_by_id() in place of the open-coded sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t) local array sizes, and move dpaa2_dev_xstats_get() below the _by_id variants to reflect the new dependency direction. No functional change: availability gating (DPNI page / DPMAC MC version), per-page dpni_get_statistics() batching and the DPMAC dpni_get_mac_statistics() path are all still performed, now solely inside dpaa2_dev_xstats_get_by_id(). Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 146 +++++++++---------------------- 1 file changed, 42 insertions(+), 104 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index b30a8e7b3d..a0c5eccf57 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -180,6 +180,9 @@ struct dpaa2_xstats_seq { struct dpni_dpmac_counters mac_cnt; }; +#define DPAA2_XSTAT_MAX_NUM \ + (sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)) + #define DPAA2_DPNI_XSTAT_MAX_NUM \ (offsetof(struct dpaa2_xstats_seq, mac_cnt) / sizeof(uint64_t)) @@ -2186,115 +2189,13 @@ dpaa2_dev_dpni_xstats_avail(struct rte_eth_dev *dev, return false; } -/* - * dpaa2_dev_xstats_get(): Get counters of dpni and dpmac. - * MAC (mac_*) counters are supported on MC version > 10.39.0 - * TC_x_policer_* counters are supported only when Policer is enable. - */ -static int -dpaa2_dev_xstats_get(struct rte_eth_dev *dev, - struct rte_eth_xstat *xstats, uint32_t n) -{ - struct fsl_mc_io *dpni = dev->process_private; - uint16_t i, j, param, stat_cnt, size; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - union dpni_statistics values; - uint8_t page_id, stat_id; - uint64_t *cnt_values; - int retcode; - - stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; - if (priv->ep_dev_type == DPAA2_MAC) - stat_cnt += DPAA2_MAC_NUM_STATS; - - if (n > stat_cnt) { - DPAA2_PMD_ERR("%s: Expected number(%d) > max number(%d)", - __func__, n, stat_cnt); - return -EINVAL; - } - - if (!xstats) - return 0; - - i = 0; - while (i < n) { - if (i >= DPAA2_MAC_XSTATS_START_ID) { - if (!dpaa2_dev_mac_xstats_avail(dev)) { - for (j = i; j < n; j++) { - xstats[j].id = j; - xstats[j].value = 0; - } - i = n; - break; - } - goto dpmac_get_xstat; - } - - page_id = 0; - stat_id = 0; - param = 0; - retcode = dpaa2_xstats_id_parse(i, &page_id, &stat_id, ¶m, &size); - if (retcode) - return retcode; - if (!dpaa2_dev_dpni_xstats_avail(dev, page_id, param)) { - xstats[i].id = i; - xstats[i].value = 0; - i++; - continue; - } - retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, - priv->token, page_id, param, &values); - if (retcode) { - DPAA2_PMD_ERR("%s: Failed(%d) to get %s's statistcis of page%d!", - __func__, retcode, dev->data->name, page_id); - return retcode; - } - cnt_values = (void *)&values; - j = stat_id; - while (i < n && j < size) { - xstats[i].id = i; - xstats[i].value = cnt_values[j]; - i++; - j++; - } - continue; - -dpmac_get_xstat: - retcode = dpaa2_dev_xstat_mac_setup_mem(dev); - if (retcode) { - DPAA2_PMD_ERR("%s: Failed(%d) to setup %s MAC statistics!", - __func__, retcode, dev->data->name); - return retcode; - } - retcode = dpni_get_mac_statistics(dpni, CMD_PRI_LOW, - priv->token, priv->cnt_idx_iova, - priv->cnt_values_iova, DPAA2_MAC_NUM_STATS); - if (retcode) { - DPAA2_PMD_ERR("%s: Failed(%d) to get %s's MAC statistics!", - __func__, retcode, dev->data->name); - return retcode; - } - cnt_values = priv->cnt_values_dma_mem; - - j = i - DPAA2_MAC_XSTATS_START_ID; - while (i < n && j < DPAA2_MAC_NUM_STATS) { - xstats[i].id = i; - xstats[i].value = cnt_values[j]; - i++; - j++; - } - } - - return i; -} - static int dpaa2_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, uint32_t limit) { struct dpaa2_dev_priv *priv = dev->data->dev_private; uint16_t i, stat_cnt; - uint64_t xstat_str[sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)]; + uint64_t xstat_str[DPAA2_XSTAT_MAX_NUM]; stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; if (priv->ep_dev_type == DPAA2_MAC) @@ -2420,7 +2321,7 @@ dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, { struct dpaa2_dev_priv *priv = dev->data->dev_private; uint16_t i, stat_cnt; - uint64_t xstat_str[sizeof(struct dpaa2_xstats_seq) / sizeof(uint64_t)]; + uint64_t xstat_str[DPAA2_XSTAT_MAX_NUM]; stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; if (priv->ep_dev_type == DPAA2_MAC) @@ -2442,6 +2343,43 @@ dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, return limit; } +/* + * dpaa2_dev_xstats_get(): Get counters of dpni and dpmac. + * MAC (mac_*) counters are supported on MC version > 10.39.0 + * TC_x_policer_* counters are supported only when Policer is enable. + */ +static int +dpaa2_dev_xstats_get(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, uint32_t n) +{ + int retcode; + uint32_t i; + uint64_t ids[DPAA2_XSTAT_MAX_NUM], vals[DPAA2_XSTAT_MAX_NUM]; + + if (!xstats || !n) + return 0; + + if (n > DPAA2_XSTAT_MAX_NUM) { + DPAA2_PMD_WARN("%s: Expected xstat number(%d) > max(%ld)", + __func__, n, DPAA2_XSTAT_MAX_NUM); + n = DPAA2_XSTAT_MAX_NUM; + } + for (i = 0; i < n; i++) { + ids[i] = i; + xstats[i].id = i; + xstats[i].value = 0; + } + + retcode = dpaa2_dev_xstats_get_by_id(dev, ids, vals, n); + if (retcode < 0) + return retcode; + + for (i = 0; i < (uint32_t)retcode; i++) + xstats[i].value = vals[i]; + + return retcode; +} + static int dpaa2_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats, struct eth_queue_stats *qstats) -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 20/65] net/dpaa2: fetch only requested MAC xstats in one MC call 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (18 preceding siblings ...) 2026-10-23 13:42 ` [PATCH v4-S3 19/65] net/dpaa2: reimplement xstats_get() on top of xstats_get_by_id() Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 21/65] net/dpaa2: rework flow with per-table profile and group types Prashant Gupta ` (44 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> dpaa2_dev_xstats_get_by_id() previously handled MAC counters by issuing dpni_get_mac_statistics() for all DPAA2_MAC_NUM_STATS counters on the first MAC id seen, caching the full result in priv->cnt_values_dma_mem, and indexing into it for the remaining MAC ids in the same call. That had two drawbacks: - Every caller that asked for even a single MAC counter paid for a full-block MC fetch. - The cnt_idx_dma_mem table was pre-populated at setup time with a fixed 0..N-1 index list, so the MC command was effectively locked to "read all counters in order". Rework the MAC path to build the index list on the fly from the ids the caller actually requested: - Drop the one-shot cnt_idx_dma_mem initialisation in dpaa2_dev_xstat_mac_setup_mem(); it now only allocates and maps the DMA buffers. - Call dpaa2_dev_xstat_mac_setup_mem() once at the top of dpaa2_dev_xstats_get_by_id() so the DMA memory is always ready. - While walking ids[], for every id in the MAC range populate mac_idx[mac_num] with the MAC counter index and remember the destination slot in mac_val[mac_num]; zero values[i] up front so unavailable MAC counters stay zero. - After the DPNI loop, if mac_num > 0 issue a single dpni_get_mac_statistics() for exactly mac_num entries and scatter the results back through mac_val[]. Removes the mac_fetched flag and the dpmac_get_xstat / dpni_get_xstat gotos. Also replace the open-coded `priv->ep_dev_type == DPAA2_MAC` checks in dpaa2_dev_xstats_get_names(), dpaa2_dev_xstats_get_names_by_id() and _get_by_id() with the existing dpaa2_dev_mac_xstats_avail() helper, so MAC xstats are only exposed when both the endpoint is DPAA2_MAC and the MC version supports them. Introduce DPAA2_MAC_XSTAT_MAX_NUM (= DPAA2_MAC_NUM_STATS) and a static_assert that DPAA2_DPNI_XSTAT_MAX_NUM + DPAA2_MAC_XSTAT_MAX_NUM equals DPAA2_XSTAT_MAX_NUM, so the DPNI+MAC id space stays consistent with struct dpaa2_xstats_seq. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 97 +++++++++++++++----------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index a0c5eccf57..5dcdc6fa76 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -186,6 +186,10 @@ struct dpaa2_xstats_seq { #define DPAA2_DPNI_XSTAT_MAX_NUM \ (offsetof(struct dpaa2_xstats_seq, mac_cnt) / sizeof(uint64_t)) +#define DPAA2_MAC_XSTAT_MAX_NUM DPAA2_MAC_NUM_STATS + +static_assert((DPAA2_DPNI_XSTAT_MAX_NUM + DPAA2_MAC_XSTAT_MAX_NUM) == DPAA2_XSTAT_MAX_NUM); + #define DPAA2_DPNI_STAT_SET_PAGE_PARAM(param) \ ({ \ int ret = false; \ @@ -2099,7 +2103,6 @@ static int dpaa2_dev_xstat_mac_setup_mem(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint32_t *cnt_idx, i; int ret = 0; if (!priv->cnt_idx_dma_mem) { @@ -2118,9 +2121,6 @@ dpaa2_dev_xstat_mac_setup_mem(struct rte_eth_dev *dev) __func__, priv->cnt_idx_dma_mem); goto err_dma_map; } - cnt_idx = priv->cnt_idx_dma_mem; - for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) - cnt_idx[i] = rte_cpu_to_le_32(i); } if (!priv->cnt_values_dma_mem) { @@ -2193,13 +2193,12 @@ static int dpaa2_dev_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, uint32_t limit) { - struct dpaa2_dev_priv *priv = dev->data->dev_private; uint16_t i, stat_cnt; uint64_t xstat_str[DPAA2_XSTAT_MAX_NUM]; stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; - if (priv->ep_dev_type == DPAA2_MAC) - stat_cnt += DPAA2_MAC_NUM_STATS; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; if (!limit) return stat_cnt; @@ -2222,20 +2221,28 @@ static int dpaa2_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, uint64_t *values, uint32_t n) { - uint16_t i, id, stat_cnt; + uint16_t i, id, stat_cnt, mac_num = 0; uint8_t page_id, stat_id; uint16_t param; struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = dev->process_private; bool page_fetched[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; - /* Fetch all MAC counters in a single MC command on first MAC xstat. */ - bool mac_fetched = false; + /* Fetch required MAC counters in a single MC command. */ int retcode; - uint64_t *cnt_values; + uint32_t *mac_idx; + uint64_t *mac_val[DPAA2_MAC_XSTAT_MAX_NUM]; + + retcode = dpaa2_dev_xstat_mac_setup_mem(dev); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to setup %s's MAC statistics!", + __func__, retcode, dev->data->name); + return retcode; + } + mac_idx = priv->cnt_idx_dma_mem; stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; - if (priv->ep_dev_type == DPAA2_MAC) - stat_cnt += DPAA2_MAC_NUM_STATS; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; memset(page_fetched, 0, sizeof(page_fetched)); @@ -2246,16 +2253,13 @@ dpaa2_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, } id = ids ? ids[i] : i; if (id >= DPAA2_MAC_XSTATS_START_ID) { - if (!dpaa2_dev_mac_xstats_avail(dev)) { - values[i] = 0; - continue; - } - if (mac_fetched) { - cnt_values = priv->cnt_values_dma_mem; - values[i] = cnt_values[id - DPAA2_MAC_XSTATS_START_ID]; - continue; + values[i] = 0; + if (dpaa2_dev_mac_xstats_avail(dev)) { + mac_idx[mac_num] = rte_cpu_to_le_32(id - DPAA2_MAC_XSTATS_START_ID); + mac_val[mac_num] = &values[i]; + mac_num++; } - goto dpmac_get_xstat; + continue; } page_id = 0; stat_id = 0; @@ -2267,35 +2271,10 @@ dpaa2_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, values[i] = 0; continue; } - if (!page_fetched[page_id][param]) - goto dpni_get_xstat; - values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; - continue; - -dpmac_get_xstat: - /* Single MC call fetches all MAC counters at once; - * reuse the result for every subsequent MAC xstat. - */ - retcode = dpaa2_dev_xstat_mac_setup_mem(dev); - if (retcode) { - DPAA2_PMD_ERR("%s: Failed(%d) to setup %s's MAC statistics!", - __func__, retcode, dev->data->name); - return retcode; - } - retcode = dpni_get_mac_statistics(dpni, CMD_PRI_LOW, - priv->token, priv->cnt_idx_iova, - priv->cnt_values_iova, DPAA2_MAC_NUM_STATS); - if (retcode) { - DPAA2_PMD_ERR("%s: Failed(%d) to get %s's MAC statistics!", - __func__, retcode, dev->data->name); - return retcode; + if (page_fetched[page_id][param]) { + values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; + continue; } - mac_fetched = true; - cnt_values = priv->cnt_values_dma_mem; - values[i] = cnt_values[id - DPAA2_MAC_XSTATS_START_ID]; - continue; - -dpni_get_xstat: /* Cache dpni page results: multiple xstats can share * the same (page_id, param), so only fetch each pair once. */ @@ -2311,6 +2290,19 @@ dpaa2_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids, values[i] = priv->pg_xstats[page_id][param].raw.counter[stat_id]; } + if (mac_num > 0) { + retcode = dpni_get_mac_statistics(dpni, CMD_PRI_LOW, + priv->token, priv->cnt_idx_iova, + priv->cnt_values_iova, mac_num); + if (retcode) { + DPAA2_PMD_ERR("%s: Failed(%d) to get %s's %d MAC statistics!", + __func__, retcode, dev->data->name, mac_num); + return retcode; + } + for (i = 0; i < mac_num; i++) + *mac_val[i] = priv->cnt_values_dma_mem[i]; + } + return n; } @@ -2319,13 +2311,12 @@ dpaa2_dev_xstats_get_names_by_id(struct rte_eth_dev *dev, const uint64_t *ids, struct rte_eth_xstat_name *xstats_names, uint32_t limit) { - struct dpaa2_dev_priv *priv = dev->data->dev_private; uint16_t i, stat_cnt; uint64_t xstat_str[DPAA2_XSTAT_MAX_NUM]; stat_cnt = DPAA2_DPNI_XSTAT_MAX_NUM; - if (priv->ep_dev_type == DPAA2_MAC) - stat_cnt += DPAA2_MAC_NUM_STATS; + if (dpaa2_dev_mac_xstats_avail(dev)) + stat_cnt += DPAA2_MAC_XSTAT_MAX_NUM; if (!ids) return dpaa2_dev_xstats_get_names(dev, xstats_names, limit); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 21/65] net/dpaa2: rework flow with per-table profile and group types 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (19 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 20/65] net/dpaa2: fetch only requested MAC xstats in one MC call Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 22/65] net/dpaa2: reimplement RSS distribution via rte_flow Prashant Gupta ` (43 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The dpaa2 PMD flow engine was built around a device-wide extract_s blob (qos_key_extract + tc_key_extract[MAX_TCS]) and a single dpaa2_dev_flow object that carried QoS and FS state side by side (qos_rule / fs_rule, qos_key_addr / fs_key_addr, ...). Growing new features onto that layout had become painful: - There was no clean way to express a "QoS only", "FS only" or "RSS" flow; everything flowed through the same code path. - IP src/dst and L4 src/dst extracts were open-coded with ip_addr_type / ip_addr_extract_pos / l4_src_port_pos state that was easy to desync when rules were added or removed. - There was no bookkeeping of which hardware entries were in use, no runtime "clean invalid extract" step, and no way to update the action on an existing rule or set per-group miss actions. - Protocol parsers were a long series of dpaa2_configure_flow_<proto>() clones that each had their own tunnel/raw/soft-parser branches and FAF handling. - QoS and FS table setup, default action programming and entry/update/remove were all duplicated. Reimplement the flow engine around a per-table profile and a per-type generic flow: Core data model (dpaa2_ethdev.h): - Replace struct extract_s and the two parallel dpaa2_key_extract arrays with struct dpaa2_flow_profile, which holds a dpaa2_flow_tbl_profile for the single QoS table and one per TC for FS/RSS. Each tbl_profile owns its dpkg extract param DMA buffer, dpni_qos_tbl_cfg / dpni_rx_dist_cfg config, default action (default_drop / default_jump / default_queue), rss_flow pointer, and an entry_map bitmap tracking used indices. - Replace the open-coded IP/L4 extract state with struct dpaa2_ip_addr_extract ip_addr[2] and struct dpaa2_l4_port_extract l4_port[DPAA2_L4_PORT_NUM], plus a key_profile that is just dpkg + prot_field[] with (type, prot, key_field, key_offset, key_size) per extract. - Delete the old DPAA2_FAFE_PSR_OFFSET / enum dpaa2_rx_faf_offset constants: FAF/PSR bit offsets are now obtained from the parser decode helpers (dpaa2_protocol_psr_bit_offset). Add new DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV (10.39.109) gating for QoS miss-flow-id action, and DPAA2_QOS_ONLY_FLOW_STEER_FLAG to force a device into QoS-only mode. Flow object model (dpaa2_flow.c): - Introduce struct dpaa2_generic_flow carrying one steering flow: type (QOS/FS/RSS), rule_cfg, key_addr/mask_addr, rule_size, entry_index, ip_key/ip_src/ip_dst, tc_id, action_type and an embedded dpaa2_dev_fs_action (dpni_fs_action_cfg + per-redir dst_name[]). A dpaa2_dev_flow now just references up to three dpaa2_generic_flow objects (qos_flow / fs_flow / rss_flow), allowing a user flow to be any combination. - Add generic flow lifecycle helpers (init / deinit / add rule / remove rule / verify entry) plus entry_map get/set so that conflicting entries are detected before HW programming. Extract/rule insertion helpers: - Centralize all extract-set operations into: dpaa2_profile_insert_ipaddr_extract(), dpaa2_profile_insert_no_ipaddr_extract(), dpaa2_dpkg_insert_extract(), dpaa2_flow_rule_insert_hole() / _dpaa2_flow_rule_insert_hole(). These are the only places that touch key_offset / key_size and move trailing extracts when a new field is inserted. - Build dpaa2_flow_extract_add_hdr / _add_soft_psr / _add_faf_psr / _add_raw on top of them, and corresponding dpaa2_flow_add_hdr_extract_rule / _add_ipaddr_extract_rule / _add_soft_psr_extract_rule / _faf_add_rule to attach actual key/mask bytes. Protocol handling: - Replace the per-protocol dpaa2_configure_flow_<proto>() set with a single dispatch table s_dpaa2_flow_proto_handle[] indexed by rte_flow_item_type. Each entry declares the item's mask, fields[], field_offset[], field_size[], its parser protocol id, tunnel protocol id and the two callbacks (normal and tunnel). New callbacks cover eth, vlan, ipv4, ipv6, icmp, udp, tcp, esp, ah, sctp, gre, gtp, vxlan, ecpri, geneve and raw with shared logic in dpaa2_flow_general_extract_rule_set() and the _tunnel_* variants; eCPRI uses the parser decode helpers. - IPv4 fragment is matched by setting the IP-frag FAF rather than the open-coded fragment_offset extract. Table and action handling: - dpaa2_flow_qos_table_config() / dpaa2_flow_tc_table_config() (re)program dpkg, set/clear RSS, write default (drop / jump / queue) action, and re-add existing rules via dpaa2_flow_add_all_steering_rule(). Default actions are gated on MC rev via DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV and DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV. - dpaa2_flow_add_steering_rule() handles add vs update (DPNI_FS_OPT_UPDATE_IF_EXISTS / DPNI_QOS_OPT_UPDATE_IF_EXISTS) and uses dpni_add_fs_entry_legacy for MC revs before DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV. - Actions are converted uniformly in dpaa2_flow_action_rxq_convert() (QUEUE), dpaa2_flow_action_tx_port_convert() (PORT_ID / REPRESENTED_PORT, with multi-redirect via DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX gated on DPNI_OPT_V8_HAS_REPLICATION), DROP (DPNI_FS_OPT_DISCARD) and JUMP (sets flow->tc_id). FS actions carry a dst_name[] array for logging. New flow APIs and group types: - Add RTE_DPAA2_FLAT_GROUP_FLOW / RTE_DPAA2_QOS_GROUP_FLOW / RTE_DPAA2_FS_GROUP_FLOW and the macros RTE_DPAA2_FLOW_GROUP_TYPE_SET / RTE_DPAA2_FLOW_GROUP_TYPE_GET / RTE_DPAA2_FLOW_GROUP_ID_GET so that callers can request a QoS-only or FS-only rule inside the standard rte_flow API by encoding the type in the high bits of attr->group. - Expose rte_dpaa2_flow_create() wrapper and rte_dpaa2_flow_group_set_miss_actions() so apps can set per-group default (drop / jump / queue) actions via rte_flow_group_set_miss_actions(). Expose rte_dpaa2_flow_validate() wrapper for apps to validate before calling rte_dpaa2_flow_create(). - dpaa2_flow_create() now: - RSS-only when actions[0]==RSS, - QoS-only when the port is QoS-only or group type is RTE_DPAA2_QOS_GROUP_FLOW or the action is JUMP, - otherwise programs a QoS entry (synthesized JUMP to the FS TC) plus an FS entry, so one user flow transparently covers QoS->FS redirection on multi-TC devices. - Implement flow actions_update by walking the three sub-flows and calling dpaa2_flow_steering_flow_action_update() / dpaa2_flow_rss_action_update() as appropriate. - Implement group_set_miss_actions() backed by dpaa2_flow_qos_table_set_default() / dpaa2_flow_fs_table_set_default() with full validation of the (drop / jump / queue) combination. - Replace the stub dpaa2_flow_query() with a dpni_dump_table() based implementation that locates the user flow's QoS and FS entries by matching key/mask against the HW dump. - Add rte_pmd_dpaa2_flow_table_query() experimental API that dumps every QoS and FS entry currently programmed in HW and cross-checks it against the PMD's software flow list. - dpaa2_flow_clean() now takes (tc_id, type) and selectively removes QoS-only, FS-only or RSS-only rules of a given TC, so that creating an FS rule in a TC automatically evicts a stale RSS rule in the same TC and vice versa. Dynamic reconfiguration and validation: - dpaa2_flow_remove_invalid_extract() walks the current extract set, drops extracts no longer referenced by any rule (including the IP-address pair and L4 port pair), shrinks each rule's key/mask buffer accordingly, recomputes key_max_size and ip_addr sizes based on each rule's ip_key (IPv4 vs IPv6), and triggers a table re-program via dpaa2_flow_table_update(). This runs on every flow destroy so the HW table stays as small as possible. - dpaa2_flow_verify_patterns(), dpaa2_flow_verify_flow_action(), dpaa2_flow_verify_steering_attr() and dpaa2_flow_check_actions_support() are reorganized around the split dpaa2_supported_fs_action_type / dpaa2_supported_qos_action_type arrays (FS now explicitly adds DROP; QoS adds JUMP) and the new group-type encoding. Debug/log: - Add DPAA2_FLOW_DUMP() going to stderr (independent of rte_log so multi-line dumps are not interleaved), controlled by env DPAA2_FLOW_CONTROL_LOG. Replace the old dpaa2_flow_qos_extracts_log / dpaa2_flow_fs_extracts_log / dpaa2_flow_qos_entry_log / dpaa2_flow_fs_entry_log quartet with a shared dpaa2_flow_extracts_log(), dpaa2_flow_steering_entry_log() and dpaa2_dump_extract_map() that work for QoS and FS uniformly and also decode the chosen action (receive to flow / redirect to port(s) / drop / jump). - Replace the hand-rolled dpaa2_prot_field_string() if/else chain with a static descriptor table dpaa2_hw_prot_field_support[] covering eth, vlan, ip, tcp, udp, sctp, icmp, gre, gtp, esp and ah, and add dpaa2_dump_dpkg() for human-readable extract dumps. Init / close (dpaa2_ethdev.c): - dpaa2_dev_init() now allocates extract_param and entry_map for every tbl_profile (QoS + MAX_TCS FS tables), stamps the default drop/jump/queue destinations, and primes tc_cfg.dist_size / key_cfg_iova per TC. - dpaa2_dev_close() frees the per-table extract_param and entry_map and calls dpaa2_flow_clean(dev, MAX_TCS, DPAA2_FLOW_ALL_TYPE) to tear down all flows. Parser decode (dpaa2_parser_decode.h): - Add DPAA2_PARSER_NULL_ID so dispatch-table slots for items that have no corresponding FAF (eCPRI/VXLAN inner, raw) can be tagged explicitly instead of leaving a magic 0. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- doc/guides/nics/dpaa2.rst | 8 + drivers/net/dpaa2/dpaa2_ethdev.c | 96 +- drivers/net/dpaa2/dpaa2_ethdev.h | 583 +- drivers/net/dpaa2/dpaa2_flow.c | 8107 ++++++++++------------- drivers/net/dpaa2/dpaa2_parser_decode.h | 9 + drivers/net/dpaa2/rte_pmd_dpaa2.h | 59 + 6 files changed, 4209 insertions(+), 4653 deletions(-) diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index 4480a5f652..6c67a76f12 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -495,6 +495,14 @@ Refer to the document :doc:`build_and_test` for details. parser result of every received packet (debug only, hurts Rx performance). e.g. ``fslmc:dpni.1,drv_rx_print_parser_result=1`` +* Use dev arg option ``drv_qos_flow_only_steer=1`` to steer ingress traffic + using the QoS table only. + e.g. ``fslmc:dpni.1,drv_qos_flow_only_steer=1`` + +* Use dev arg option ``drv_flow_api_debug=1`` to enable debug logs for the flow + create, destroy and update operations. + e.g. ``fslmc:dpni.1,drv_flow_api_debug=1`` + * Use dev arg option ``drv_error_queue=1`` to enable Packets in Error queue. DPAA2 hardware drops the error packet in hardware. This option enables the hardware to not drop the error packet and let the driver dump the error diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 5dcdc6fa76..9ad4494ab0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -81,6 +81,16 @@ dpaa2_dev_args_parser_offset_en(void *vdev, priv->psr_dynfield_offset = ret | DPAA2_PSR_DYNFIELD_OFFSET_EN; } +static void +dpaa2_dev_args_qos_entries_per_tc(void *vdev, + const struct rte_kvargs_pair *pair) +{ + struct rte_eth_dev *dev = vdev; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + priv->qos_entries_per_tc = atoi(pair->value); +} + /* Single source of truth for dpaa2 devargs: * ENTRY(key-string, handle, flag-bit) * handle is an optional per-arg callback (NULL if the arg only sets a flag). @@ -98,7 +108,11 @@ dpaa2_dev_args_parser_offset_en(void *vdev, ENTRY("drv_err_queue", NULL, DPAA2_RX_ERROR_QUEUE_FLAG) \ ENTRY("drv_no_taildrop", NULL, DPAA2_RX_TAILDROP_OFF) \ ENTRY("drv_no_data_stashing", NULL, DPAA2_RX_DATA_STASHING_OFF_FLAG) \ - ENTRY("drv_parse_protocol_offset", dpaa2_dev_args_parser_offset_en, 0) + ENTRY("drv_parse_protocol_offset", dpaa2_dev_args_parser_offset_en, 0) \ + ENTRY("drv_qos_entries_per_tc", dpaa2_dev_args_qos_entries_per_tc, \ + DPAA2_QOS_ENTRIES_PER_TC_FLAG) \ + ENTRY("drv_qos_flow_only_steer", NULL, DPAA2_QOS_FLOW_ONLY_STEER_FLAG) \ + ENTRY("drv_flow_api_debug", NULL, DPAA2_FLOW_API_DEBUG_FLAG) #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_REPEAT_TIME 90 /* 9s (90 * 100ms) in total */ @@ -1833,6 +1847,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) struct fsl_mc_io *dpni = dev->process_private; int i, ret; struct rte_eth_link link; + struct dpaa2_flow_tbl_profile *tbl_profile; PMD_INIT_FUNC_TRACE(); @@ -1845,7 +1860,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) } dpaa2_tm_deinit(dev); - dpaa2_flow_clean(dev); + dpaa2_flow_clean(dev, MAX_TCS, DPAA2_FLOW_ALL_TYPE); /* Clean the device first */ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); if (ret) { @@ -1869,20 +1884,24 @@ dpaa2_dev_close(struct rte_eth_dev *dev) } /* Close the device at underlying layer*/ ret = dpni_close(dpni, CMD_PRI_LOW, priv->token); - if (ret) { - DPAA2_PMD_ERR("Failure closing dpni device with err code %d", - ret); - } + if (ret) + DPAA2_PMD_ERR("Failure closing dpni device with err code %d", ret); /* Free the allocated memory for ethernet private data and dpni*/ priv->hw = NULL; dev->process_private = NULL; rte_free(dpni); - for (i = 0; i < MAX_TCS; i++) - rte_free(priv->extract.tc_extract_param[i]); - - rte_free(priv->extract.qos_extract_param); + for (i = 0; i < (MAX_TCS + 1); i++) { + if (i < MAX_TCS) + tbl_profile = &priv->flow_profile.tc_profile[i]; + else + tbl_profile = &priv->flow_profile.qos_profile; + rte_free(tbl_profile->extract_param); + tbl_profile->extract_param = NULL; + rte_free(tbl_profile->entry_map); + tbl_profile->entry_map = NULL; + } rte_free(priv->cnt_idx_dma_mem); rte_free(priv->cnt_values_dma_mem); @@ -3555,8 +3574,10 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) struct dpni_attr attr; struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; struct dpni_buffer_layout layout; - int ret, hw_id, i; + int ret, hw_id, i, entry_num; uint16_t num_q_per_tc, max_q_per_tc; + struct dpaa2_flow_tbl_profile *tbl_profile; + uint64_t iova; PMD_INIT_FUNC_TRACE(); @@ -3635,6 +3656,11 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + if (priv->qos_entries_per_tc * priv->num_rx_tc > priv->qos_entries) { + DPAA2_PMD_WARN("QoS entries per TC(%d) x tc num(%d) > total entries(%d)", + priv->qos_entries_per_tc, priv->num_rx_tc, priv->qos_entries); + } + /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) { priv->max_cgs = attr.num_cgs; @@ -3754,26 +3780,42 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } /* Init fields w.r.t. classification */ - memset(&priv->extract.qos_key_extract, 0, - sizeof(struct dpaa2_key_extract)); - priv->extract.qos_extract_param = rte_zmalloc(NULL, - DPAA2_EXTRACT_PARAM_MAX_SIZE, - RTE_CACHE_LINE_SIZE); - if (!priv->extract.qos_extract_param) { - DPAA2_PMD_ERR("Memory alloc failed"); - goto init_err; - } - - for (i = 0; i < MAX_TCS; i++) { - memset(&priv->extract.tc_key_extract[i], 0, - sizeof(struct dpaa2_key_extract)); - priv->extract.tc_extract_param[i] = rte_zmalloc(NULL, + for (i = 0; i < (MAX_TCS + 1); i++) { + if (i < MAX_TCS) { + tbl_profile = &priv->flow_profile.tc_profile[i]; + entry_num = priv->fs_entries; + } else { + tbl_profile = &priv->flow_profile.qos_profile; + entry_num = priv->qos_entries; + } + memset(tbl_profile, 0, sizeof(struct dpaa2_flow_tbl_profile)); + tbl_profile->extract_param = rte_zmalloc(NULL, DPAA2_EXTRACT_PARAM_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!priv->extract.tc_extract_param[i]) { - DPAA2_PMD_ERR("Memory alloc failed"); + if (!tbl_profile->extract_param) goto init_err; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(tbl_profile->extract_param, + DPAA2_EXTRACT_PARAM_MAX_SIZE); + tbl_profile->default_drop = false; + if (i < MAX_TCS) { + tbl_profile->tc_cfg.dist_size = priv->dist_queues; + tbl_profile->tc_cfg.key_cfg_iova = iova; + tbl_profile->tc_cfg.tc = i; + /** First flow of TC as default flow, otherwise, may be dropped.*/ + tbl_profile->default_queue.index = priv->dist_queues * i; + } else { + tbl_profile->qos_cfg.key_cfg_iova = iova; + tbl_profile->qos_cfg.keep_entries = true; + /** First TC as default TC, otherwise, may be dropped.*/ + tbl_profile->default_jump.group = 0; } + if (!entry_num) + continue; + + tbl_profile->entry_map = rte_zmalloc(NULL, entry_num / 8 + 1, 0); + if (!tbl_profile->entry_map) + goto init_err; + tbl_profile->entry_map_size = entry_num / 8 + 1; } ret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e2d9d5de36..e3fb3f8920 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -109,6 +109,12 @@ #define DPAA2_IEEE1588_RX_TS_FLAG RTE_BIT32(13) +#define DPAA2_QOS_ENTRIES_PER_TC_FLAG RTE_BIT32(14) + +#define DPAA2_QOS_FLOW_ONLY_STEER_FLAG RTE_BIT32(15) + +#define DPAA2_FLOW_API_DEBUG_FLAG RTE_BIT32(16) + /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -206,6 +212,7 @@ #define DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 106) #define DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 109) #define DPAA2_MAC_XSTATS_MC_REV RTE_FSL_MC_REV(10, 39, 109) /* mac counters */ @@ -256,124 +263,15 @@ struct dpaa2_dyn_rx_protocol_pos { #define DPAA2_FS_FLC_FLOW_OFFSET \ (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) -#define DPAA2_FAPR_SIZE \ - (sizeof(struct dpaa2_annot_hdr) - \ - offsetof(struct dpaa2_annot_hdr, word3)) - -#define DPAA2_PR_NXTHDR_OFFSET 0 - -#define DPAA2_FAFE_PSR_OFFSET 2 -#define DPAA2_FAFE_PSR_SIZE 2 - -#define DPAA2_FAF_PSR_OFFSET 4 -#define DPAA2_FAF_PSR_SIZE 12 - -#define DPAA2_FAF_TOTAL_SIZE \ - (DPAA2_FAFE_PSR_SIZE + DPAA2_FAF_PSR_SIZE) - -/* Just most popular Frame attribute flags (FAF) here.*/ -enum dpaa2_rx_faf_offset { - /* Set by SP start*/ - FAFE_VXLAN_IN_VLAN_FRAM = 0, - FAFE_VXLAN_IN_IPV4_FRAM = 1, - FAFE_VXLAN_IN_IPV6_FRAM = 2, - FAFE_VXLAN_IN_UDP_FRAM = 3, - FAFE_VXLAN_IN_TCP_FRAM = 4, - - FAFE_ECPRI_FRAM = 7, - /* Set by SP end*/ - - FAF_GTP_PRIMED_FRAM = 1 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_PTP_FRAM = 3 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_VXLAN_FRAM = 4 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ETH_FRAM = 10 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_LLC_SNAP_FRAM = 18 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_VLAN_FRAM = 21 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_PPPOE_PPP_FRAM = 25 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_MPLS_FRAM = 27 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ARP_FRAM = 30 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPV4_FRAM = 34 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPV6_FRAM = 42 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IP_FRAM = 48 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IP_FRAG_FRAM = 50 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ICMP_FRAM = 57 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IGMP_FRAM = 58 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_GRE_FRAM = 65 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_UDP_FRAM = 70 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_TCP_FRAM = 72 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_FRAM = 77 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_ESP_FRAM = 78 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_IPSEC_AH_FRAM = 79 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_SCTP_FRAM = 81 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_DCCP_FRAM = 83 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_GTP_FRAM = 87 + DPAA2_FAFE_PSR_SIZE * 8, - FAF_ESP_FRAM = 89 + DPAA2_FAFE_PSR_SIZE * 8, -}; - -enum dpaa2_ecpri_fafe_type { - ECPRI_FAFE_TYPE_0 = (8 - FAFE_ECPRI_FRAM), - ECPRI_FAFE_TYPE_1 = (8 - FAFE_ECPRI_FRAM) | (1 << 1), - ECPRI_FAFE_TYPE_2 = (8 - FAFE_ECPRI_FRAM) | (2 << 1), - ECPRI_FAFE_TYPE_3 = (8 - FAFE_ECPRI_FRAM) | (3 << 1), - ECPRI_FAFE_TYPE_4 = (8 - FAFE_ECPRI_FRAM) | (4 << 1), - ECPRI_FAFE_TYPE_5 = (8 - FAFE_ECPRI_FRAM) | (5 << 1), - ECPRI_FAFE_TYPE_6 = (8 - FAFE_ECPRI_FRAM) | (6 << 1), - ECPRI_FAFE_TYPE_7 = (8 - FAFE_ECPRI_FRAM) | (7 << 1) -}; - -#define DPAA2_PR_ETH_OFF_OFFSET 19 -#define DPAA2_PR_TCI_OFF_OFFSET 21 -#define DPAA2_PR_LAST_ETYPE_OFFSET 23 -#define DPAA2_PR_L3_OFF_OFFSET 27 -#define DPAA2_PR_L4_OFF_OFFSET 30 -#define DPAA2_PR_L5_OFF_OFFSET 31 -#define DPAA2_PR_NXTHDR_OFF_OFFSET 34 - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 -struct ipv4_sd_addr_extract_rule { - uint32_t ipv4_src; - uint32_t ipv4_dst; -}; - -struct ipv6_sd_addr_extract_rule { - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; -}; - -struct ipv4_ds_addr_extract_rule { - uint32_t ipv4_dst; - uint32_t ipv4_src; -}; - -struct ipv6_ds_addr_extract_rule { - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; -}; - -union ip_addr_extract_rule { - struct ipv4_sd_addr_extract_rule ipv4_sd_addr; - struct ipv6_sd_addr_extract_rule ipv6_sd_addr; - struct ipv4_ds_addr_extract_rule ipv4_ds_addr; - struct ipv6_ds_addr_extract_rule ipv6_ds_addr; -}; - -union ip_src_addr_extract_rule { - uint32_t ipv4_src; - uint8_t ipv6_src[NH_FLD_IPV6_ADDR_SIZE]; -}; - -union ip_dst_addr_extract_rule { - uint32_t ipv4_dst; - uint8_t ipv6_dst[NH_FLD_IPV6_ADDR_SIZE]; -}; - -enum ip_addr_extract_type { - IP_NONE_ADDR_EXTRACT, - IP_SRC_EXTRACT, - IP_DST_EXTRACT, - IP_SRC_DST_EXTRACT, - IP_DST_SRC_EXTRACT +enum dpaa2_flow_dist_type { + DPAA2_FLOW_NULL_TYPE = 0, + DPAA2_FLOW_QOS_TYPE = 1 << 0, + DPAA2_FLOW_FS_TYPE = 1 << 1, + DPAA2_FLOW_RSS_TYPE = 1 << 2, + DPAA2_FLOW_ALL_TYPE = (DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE | + DPAA2_FLOW_RSS_TYPE) }; enum key_prot_type { @@ -389,47 +287,61 @@ struct key_prot_field { enum key_prot_type type; enum net_prot prot; uint32_t key_field; + uint8_t key_offset; + uint8_t key_size; +}; + +struct dpaa2_ip_addr_extract { + uint32_t field; + uint8_t max_size; + uint8_t extract_idx; }; -struct dpaa2_raw_region { - uint8_t raw_start; - uint8_t raw_size; +struct dpaa2_l4_port_extract { + uint8_t present; + uint8_t extract_idx; + uint8_t key_offset; +}; + +enum dpaa2_l4_port_type { + DPAA2_L4_SRC_PORT, + DPAA2_L4_DST_PORT, + DPAA2_L4_PORT_NUM }; struct dpaa2_key_profile { - uint8_t num; - uint8_t key_offset[DPKG_MAX_NUM_OF_EXTRACTS]; - uint8_t key_size[DPKG_MAX_NUM_OF_EXTRACTS]; - - enum ip_addr_extract_type ip_addr_type; - uint8_t ip_addr_extract_pos; - uint8_t ip_addr_extract_off; - - uint8_t raw_extract_pos; - uint8_t raw_extract_off; - uint8_t raw_extract_num; - - uint8_t l4_src_port_present; - uint8_t l4_src_port_pos; - uint8_t l4_src_port_offset; - uint8_t l4_dst_port_present; - uint8_t l4_dst_port_pos; - uint8_t l4_dst_port_offset; + struct dpkg_profile_cfg dpkg; + struct dpaa2_ip_addr_extract ip_addr[2]; + struct dpaa2_l4_port_extract l4_port[DPAA2_L4_PORT_NUM]; + uint8_t ip_addr_offset; struct key_prot_field prot_field[DPKG_MAX_NUM_OF_EXTRACTS]; uint16_t key_max_size; - struct dpaa2_raw_region raw_region; }; -struct dpaa2_key_extract { - struct dpkg_profile_cfg dpkg; +struct dpaa2_flow_tbl_profile { struct dpaa2_key_profile key_profile; + uint8_t *extract_param; + uint16_t entry_num; + uint16_t entry_map_size; + uint8_t *entry_map; + int enabled; + void *rss_flow; + union { + struct dpni_qos_tbl_cfg qos_cfg; + struct dpni_rx_dist_cfg tc_cfg; + }; + int default_drop; + union { + struct rte_flow_action_jump default_jump; + struct rte_flow_action_queue default_queue; + }; }; -struct extract_s { - struct dpaa2_key_extract qos_key_extract; - struct dpaa2_key_extract tc_key_extract[MAX_TCS]; - uint8_t *qos_extract_param; - uint8_t *tc_extract_param[MAX_TCS]; +struct dpaa2_flow_profile { + struct dpaa2_flow_tbl_profile qos_profile; + struct dpaa2_flow_tbl_profile tc_profile[MAX_TCS]; + void *mempool[MAX_TCS]; + uint8_t bp_idx[MAX_TCS]; }; enum dpaa2_tx_conf_type { @@ -460,6 +372,20 @@ struct dpaa2_dev_priv { uint8_t num_rx_tc; uint8_t num_tx_tc; uint16_t qos_entries; + /* Number of QoS table entries allocated per RX traffic class (TC). + * This field can be configured by devargs "drv_qos_entries_per_tc=x", + * Recommend values: + * 1) qos_entries / num_rx_tc + * Entries are split evenly across TCs. A QoS entry's priority + * is determined by the TC it directs traffic to. + * 2) 0 + * Priority is not tied to a TC; the user sets the priority of + * each QoS entry explicitly. + * 3) fs_entries + * Enables a two-level table. The action of a QoS entry is to + * jump to the specified FS (flow-steering) table. + */ + uint16_t qos_entries_per_tc; uint16_t fs_entries; uint8_t dist_queues; uint8_t num_channels; @@ -483,7 +409,7 @@ struct dpaa2_dev_priv { uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */ char ep_name[RTE_DEV_NAME_MAX_LEN]; - struct extract_s extract; + struct dpaa2_flow_profile flow_profile; uint16_t ss_offset; uint64_t ss_iova; @@ -522,7 +448,6 @@ struct dpaa2_dev_priv { */ union dpni_statistics pg_xstats[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; - struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; @@ -590,6 +515,367 @@ dpaa2_timestamp_debug(struct dpaa2_dev_priv *priv, prefix, timestamp, (int64_t)ts.tv_sec, (int64_t)ts.tv_nsec); } +#define DPAA2_FLOW_DUMP dpaa2_dump_print + +#define DPAA2_PROT_FIELD_MAX_NUM 10 +struct dpaa2_prot_field_desc { + uint32_t prot; + const char *prot_nm; + uint8_t field_num; + uint32_t field[DPAA2_PROT_FIELD_MAX_NUM]; + const char *field_nm[DPAA2_PROT_FIELD_MAX_NUM]; +}; + +static inline uint32_t +dpaa2_prot_field_string(uint32_t prot, uint32_t field, char *string) +{ + uint32_t i = 0, j = 0, offset; + const struct dpaa2_prot_field_desc dpaa2_hw_prot_field_support[] = { + { + NET_PROT_ETH, "eth", 3, + .field = {NH_FLD_ETH_DA, NH_FLD_ETH_SA, NH_FLD_ETH_TYPE}, + .field_nm = {"dst", "src", "type"} + }, + { + NET_PROT_VLAN, "vlan", 1, + .field = {NH_FLD_VLAN_TCI}, + .field_nm = {"tci"} + }, + { + NET_PROT_IP, "ip", 3, + .field = {NH_FLD_IP_DST, NH_FLD_IP_SRC, NH_FLD_IP_PROTO}, + .field_nm = {"dst", "src", "protocol"} + }, + { + NET_PROT_TCP, "tcp", 2, + .field = {NH_FLD_TCP_PORT_DST, NH_FLD_TCP_PORT_SRC}, + .field_nm = {"dst", "src"} + }, + { + NET_PROT_UDP, "udp", 2, + .field = {NH_FLD_UDP_PORT_DST, NH_FLD_UDP_PORT_SRC}, + .field_nm = {"dst", "src"} + }, + { + NET_PROT_SCTP, "sctp", 2, + .field = {NH_FLD_SCTP_PORT_DST, NH_FLD_SCTP_PORT_SRC}, + .field_nm = {"dst", "src"} + }, + { + NET_PROT_ICMP, "icmp", 2, + .field = {NH_FLD_ICMP_TYPE, NH_FLD_ICMP_CODE}, + .field_nm = {"type", "code"} + }, + { + NET_PROT_GRE, "gre", 1, + .field = {NH_FLD_GRE_TYPE}, + .field_nm = {"type"} + }, + { + NET_PROT_GTP, "gtp", 1, + .field = {NH_FLD_GTP_TEID}, + .field_nm = {"teid"} + }, + { + NET_PROT_IPSEC_ESP, "esp", 2, + .field = {NH_FLD_IPSEC_ESP_SPI, NH_FLD_IPSEC_ESP_SEQUENCE_NUM}, + .field_nm = {"spi", "seq"} + }, + { + NET_PROT_IPSEC_AH, "esp", 1, + .field = {NH_FLD_IPSEC_AH_SPI}, + .field_nm = {"spi"} + } + }; + + for (i = 0; i < RTE_DIM(dpaa2_hw_prot_field_support); i++) { + if (prot != dpaa2_hw_prot_field_support[i].prot) + continue; + for (j = 0; j < dpaa2_hw_prot_field_support[i].field_num; j++) { + if (field == dpaa2_hw_prot_field_support[i].field[j]) + break; + } + break; + } + + if (i == RTE_DIM(dpaa2_hw_prot_field_support)) + return sprintf(string, "unknown protocol(%d)", prot); + + offset = sprintf(string, "%s.", dpaa2_hw_prot_field_support[i].prot_nm); + if (j == dpaa2_hw_prot_field_support[i].field_num) { + offset += sprintf(&string[offset], "unknown field(%d)", + field); + } else { + offset += sprintf(&string[offset], "%s", + dpaa2_hw_prot_field_support[i].field_nm[j]); + } + return offset; +} + +static inline void +dpaa2_dump_dpkg(const struct dpkg_profile_cfg *dpkg) +{ + int idx; + char string[1024]; + const struct dpkg_extract *extract; + enum dpkg_extract_type type; + enum net_prot prot; + uint32_t field; + + for (idx = 0; idx < dpkg->num_extracts; idx++) { + extract = &dpkg->extracts[idx]; + type = extract->type; + if (type == DPKG_EXTRACT_FROM_HDR) { + prot = extract->extract.from_hdr.prot; + field = extract->extract.from_hdr.field; + dpaa2_prot_field_string(prot, field, string); + DPAA2_FLOW_DUMP("%s", string); + } else if (type == DPKG_EXTRACT_FROM_DATA) { + DPAA2_FLOW_DUMP("raw offset/len: %d/%d", + extract->extract.from_data.offset, + extract->extract.from_data.size); + } else if (type == DPKG_EXTRACT_FROM_PARSE) { + DPAA2_FLOW_DUMP("parse offset/len: %d/%d", + extract->extract.from_parse.offset, + extract->extract.from_parse.size); + } + if ((idx + 1) < dpkg->num_extracts) + DPAA2_FLOW_DUMP(" / "); + } + DPAA2_FLOW_DUMP("\n"); +} + +static inline int +dpaa2_extract_last_none_ip_addr_idx(const struct dpaa2_key_profile *profile) +{ + if (!profile->dpkg.num_extracts) + return -ENXIO; + if (profile->ip_addr[0].field) + return (int)profile->ip_addr[0].extract_idx - 1; + return profile->dpkg.num_extracts - 1; +} + +static inline int +dpaa2_extract_ip_convert(enum net_prot *prot, uint32_t *field) +{ + if (*prot == NET_PROT_IPV4) { + if (*field != NH_FLD_IPV4_SRC_IP && *field != NH_FLD_IPV4_DST_IP) + return -EINVAL; + + *prot = NET_PROT_IP; + *field = *field == NH_FLD_IPV4_SRC_IP ? NH_FLD_IP_SRC : NH_FLD_IP_DST; + } else if (*prot == NET_PROT_IPV6) { + if (*field != NH_FLD_IPV6_SRC_IP && + *field != NH_FLD_IPV6_DST_IP) + return -EINVAL; + + *prot = NET_PROT_IP; + *field = *field == NH_FLD_IPV4_SRC_IP ? NH_FLD_IP_SRC : NH_FLD_IP_DST; + } else if (*prot == NET_PROT_IP) { + if (*field != NH_FLD_IP_SRC && *field != NH_FLD_IP_DST) + return -EINVAL; + } else { + return -EINVAL; + } + + return 0; +} + +static inline uint8_t +dpaa2_extract_ip_addr_size(const struct dpaa2_ip_addr_extract *ip_addr) +{ + uint8_t i, ip_addr_size = 0; + + for (i = 0; i < 2; i++) { + if (ip_addr[i].field) + ip_addr_size += ip_addr[i].max_size; + } + + return ip_addr_size; +} + +static inline int +dpaa2_extract_ip_addr_add(struct dpaa2_key_profile *key_profile, + uint32_t field, uint8_t size, int *update, int last_nipa_idx) +{ + struct dpaa2_ip_addr_extract *ip_addr; + uint8_t i = 0; + char log_buf[128]; + + if (field != NH_FLD_IP_SRC && field != NH_FLD_IP_DST) + return -EINVAL; + + ip_addr = key_profile->ip_addr; + key_profile->key_max_size -= dpaa2_extract_ip_addr_size(ip_addr); + while (i < 2) { + if (ip_addr[i].field == field) { + if (size > ip_addr[i].max_size) + ip_addr[i].max_size = size; + break; + } + if (!ip_addr[i].field) { + ip_addr[i].field = field; + ip_addr[i].max_size = size; + if (update) + *update = 1; + break; + } + i++; + } + if (i > 1) { + sprintf(log_buf, + "field[0](%d)/size[0](%d)/idx[0](%d)/field[1](%d)/size[1](%d)/idx[1](%d)", + ip_addr[0].field, ip_addr[0].max_size, ip_addr[1].extract_idx, + ip_addr[0].field, ip_addr[0].max_size, ip_addr[1].extract_idx); + fprintf(stderr, "Invalid IP address extracts:%s\n", log_buf); + return -EINVAL; + } + ip_addr[i].extract_idx = last_nipa_idx < 0 ? i : (last_nipa_idx + 1) + i; + + key_profile->key_max_size += dpaa2_extract_ip_addr_size(ip_addr); + + return i; +} + +static inline int +dpaa2_profile_insert_ipaddr_extract(struct dpaa2_key_profile *profile, + enum net_prot prot, uint32_t field, uint8_t *key_addr, uint8_t *mask_addr, + const void *key, const void *mask, int size, uint8_t *rule_size, int *recfg) +{ + int update = 0, ret, last_nipa_idx = 0, ip_idx; + struct key_prot_field *last_nipa_key = NULL; + uint8_t num; + uint8_t ip_addr_offset = 0; + + ret = dpaa2_extract_ip_convert(&prot, &field); + if (ret) { + dpaa2_dump_print("Invalid IP protocol/field"); + return -EINVAL; + } + + num = profile->dpkg.num_extracts; + + if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + dpaa2_dump_print("Number of extracts overflows"); + return -EINVAL; + } + + last_nipa_idx = dpaa2_extract_last_none_ip_addr_idx(profile); + if (last_nipa_idx >= 0) { + last_nipa_key = &profile->prot_field[last_nipa_idx]; + ip_addr_offset = last_nipa_key->key_offset + last_nipa_key->key_size; + } + + ip_idx = dpaa2_extract_ip_addr_add(profile, field, size, &update, last_nipa_idx); + if (ip_idx < 0) { + dpaa2_dump_print("Failed(%d) to add IP address extract", ip_idx); + return ip_idx; + } + if (ip_idx > 1) { + dpaa2_dump_print("Invalid IP address extract index(%d)", ip_idx); + return -EINVAL; + } + if (update) { + profile->prot_field[num].type = DPAA2_NET_PROT_KEY; + profile->prot_field[num].prot = prot; + profile->prot_field[num].key_field = field; + + profile->dpkg.extracts[num].type = DPKG_EXTRACT_FROM_HDR; + profile->dpkg.extracts[num].extract.from_hdr.prot = prot; + profile->dpkg.extracts[num].extract.from_hdr.field = field; + profile->dpkg.extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD; + profile->dpkg.num_extracts++; + + if (recfg) + *recfg = true; + } + + if (key_addr && mask_addr) { + key_addr += ip_addr_offset; + mask_addr += ip_addr_offset; + if (ip_idx > 0) { + key_addr += size; + mask_addr += size; + } + rte_memcpy(key_addr, key, size); + rte_memcpy(mask_addr, mask, size); + } + if (rule_size) + *rule_size = ip_addr_offset + size * (ip_idx + 1); + + profile->ip_addr_offset = ip_addr_offset; + + return 0; +} + +static inline uint8_t +dpaa2_profile_insert_no_ipaddr_extract(struct dpaa2_key_profile *profile, + uint8_t size, uint8_t *poffset, int *ppos, const struct key_prot_field *insert) +{ + uint8_t idx, ip_addr_num = 0, offset = 0xff; + struct key_prot_field *key = profile->prot_field; + + if (profile->ip_addr[0].field && profile->ip_addr[1].field) + ip_addr_num = 2; + else if (profile->ip_addr[0].field) + ip_addr_num = 1; + + idx = profile->dpkg.num_extracts - ip_addr_num; + + if (ip_addr_num && idx > 0) + offset = key[idx - 1].key_offset + key[idx - 1].key_size; + else if (ip_addr_num) + offset = 0; + + if (idx > 0) + key[idx].key_offset = key[idx - 1].key_offset + key[idx - 1].key_size; + else + key[idx].key_offset = 0; + if (ppos) + *ppos = key[idx].key_offset; + key[idx].key_size = size; + profile->key_max_size += size; + + memmove(&key[idx + 1], &key[idx], sizeof(struct key_prot_field) * ip_addr_num); + + if (poffset) + *poffset = offset; + + if (insert) { + key[idx].type = insert->type; + key[idx].prot = insert->prot; + key[idx].key_field = insert->key_field; + } + + if (ip_addr_num) { + if (profile->ip_addr[0].field) + profile->ip_addr[0].extract_idx++; + if (profile->ip_addr[1].field) + profile->ip_addr[1].extract_idx++; + profile->ip_addr_offset += size; + } + + return idx; +} + +static inline void +dpaa2_dpkg_insert_extract(struct dpkg_profile_cfg *kg_cfg, + int idx, const struct dpkg_extract *extract) +{ + int i; + + if (idx != kg_cfg->num_extracts) { + /* Not the last extract index, must have IP address extract.*/ + for (i = kg_cfg->num_extracts - 1; i >= idx; i--) { + rte_memcpy(&kg_cfg->extracts[i + 1], + &kg_cfg->extracts[i], sizeof(struct dpkg_extract)); + } + } + + rte_memcpy(&kg_cfg->extracts[idx], extract, sizeof(struct dpkg_extract)); + kg_cfg->num_extracts++; +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); @@ -649,7 +935,8 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, struct rte_mbuf **bufs, uint16_t nb_pkts); void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); -void dpaa2_flow_clean(struct rte_eth_dev *dev); +void dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id, + enum dpaa2_flow_dist_type type); uint16_t dpaa2_dev_tx_conf(void *txq, int drain); void diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 72958c0f93..a22af4f33b 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2026 NXP + * Copyright 2018-2022, 2026 NXP */ #include <sys/queue.h> @@ -16,6 +16,7 @@ #include <rte_flow_driver.h> #include <rte_tailq.h> +#include <eal_export.h> #include <fsl_dpni.h> #include <fsl_dpkg.h> @@ -23,46 +24,53 @@ #include <dpaa2_pmd_logs.h> #include "dpaa2_parser_decode.h" -static char *dpaa2_flow_control_log; - /* Default size of a key */ -#define DPNI_DEFAULT_KEY_SIZE 24 +#define DPNI_DEFAULT_KEY_SIZE 24 enum dpaa2_flow_entry_size { DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; -enum dpaa2_flow_dist_type { - DPAA2_FLOW_QOS_TYPE = 1 << 0, - DPAA2_FLOW_FS_TYPE = 1 << 1 -}; - #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 -#define DPAA2_PROT_FIELD_STRING_SIZE 16 + #define VXLAN_HF_VNI 0x08 +#define DPAA2_MAX_ACTION_PER_FLOW_NUM 4 + +struct dpaa2_dev_fs_action { + struct dpni_fs_action_cfg action_cfg; + char dst_name[DPNI_FS_REDIR_MAX_NUM][RTE_ETH_NAME_MAX_LEN]; +}; + +struct dpaa2_generic_flow { + enum dpaa2_flow_dist_type type; + struct dpni_rule_cfg rule_cfg; + uint8_t *key_addr; + uint8_t *mask_addr; + uint8_t rule_size; + uint16_t entry_index; + /** This flow has IPv4 or IPv6 extracts.*/ + enum net_prot ip_key; + /** This flow has IPv4 or IPv6 source extract.*/ + enum net_prot ip_src; + /** This flow has IPv4 or IPv6 destination extract.*/ + enum net_prot ip_dst; + struct dpaa2_dev_priv *priv; + uint8_t tc_id; + enum rte_flow_action_type action_type; + struct dpaa2_dev_fs_action fs_action; +}; struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; - struct dpni_rule_cfg qos_rule; - uint8_t *qos_key_addr; - uint8_t *qos_mask_addr; - uint16_t qos_rule_size; - struct dpni_rule_cfg fs_rule; - uint8_t qos_real_key_size; - uint8_t fs_real_key_size; - uint8_t *fs_key_addr; - uint8_t *fs_mask_addr; - uint16_t fs_rule_size; - uint8_t tc_id; /** Traffic Class ID. */ - uint8_t tc_index; /** index within this Traffic Class. */ - enum rte_flow_action_type action_type; - struct dpni_fs_action_cfg fs_action_cfg; + struct dpaa2_generic_flow *qos_flow; + struct dpaa2_generic_flow *fs_flow; + struct dpaa2_generic_flow *rss_flow; }; -struct rte_dpaa2_flow_item { - struct rte_flow_item generic_item; +struct dpaa2_flow_item { + struct rte_flow_item item; int in_tunnel; }; @@ -81,48 +89,80 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_RAW, RTE_FLOW_ITEM_TYPE_MPLS, RTE_FLOW_ITEM_TYPE_PPPOES, - RTE_FLOW_ITEM_TYPE_RAW + /** Hardware parser supports vlan protocol only.*/ + RTE_FLOW_ITEM_TYPE_VXLAN }; static const enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI + RTE_FLOW_ITEM_TYPE_ECPRI, + RTE_FLOW_ITEM_TYPE_GENEVE }; -static const -enum rte_flow_action_type dpaa2_supported_action_type[] = { - RTE_FLOW_ACTION_TYPE_END, - RTE_FLOW_ACTION_TYPE_QUEUE, - RTE_FLOW_ACTION_TYPE_PORT_ID, - RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS, +#define DPAA2_SUPPORTED_FLOW_ACTION_TYPE \ + RTE_FLOW_ACTION_TYPE_QUEUE, \ + RTE_FLOW_ACTION_TYPE_PORT_ID, \ + RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, \ + RTE_FLOW_ACTION_TYPE_RSS, \ RTE_FLOW_ACTION_TYPE_DROP + +static const enum rte_flow_action_type dpaa2_supported_fs_action_type[] = { + DPAA2_SUPPORTED_FLOW_ACTION_TYPE +}; + +static const enum rte_flow_action_type dpaa2_supported_qos_action_type[] = { + DPAA2_SUPPORTED_FLOW_ACTION_TYPE, + RTE_FLOW_ACTION_TYPE_JUMP }; +#define DPAA2_FLOW_HDR_HEX_DUMP_SIZE \ + (RTE_MAX(sizeof(struct rte_flow_item_eth), \ + RTE_MAX(sizeof(struct rte_flow_item_vlan), \ + RTE_MAX(sizeof(struct rte_flow_item_ipv4), \ + RTE_MAX(sizeof(struct rte_flow_item_ipv6), \ + RTE_MAX(sizeof(struct rte_flow_item_icmp), \ + RTE_MAX(sizeof(struct rte_flow_item_udp), \ + RTE_MAX(sizeof(struct rte_flow_item_tcp), \ + RTE_MAX(sizeof(struct rte_flow_item_sctp), \ + RTE_MAX(sizeof(struct rte_flow_item_gre), \ + RTE_MAX(sizeof(struct rte_flow_item_ah), \ + RTE_MAX(sizeof(struct rte_flow_item_esp), \ + RTE_MAX(sizeof(struct rte_flow_item_vxlan), \ + RTE_MAX(sizeof(struct rte_flow_item_ecpri), \ + sizeof(struct rte_flow_item_gtp)))))))))))))) * 10) + #ifndef __cplusplus static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = { - .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - .hdr.src_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - .hdr.ether_type = RTE_BE16(0xffff), + .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", + .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", + .type = RTE_BE16(0xffff), }; static const struct rte_flow_item_vlan dpaa2_flow_item_vlan_mask = { - .hdr.vlan_tci = RTE_BE16(0xffff), + .tci = RTE_BE16(0xffff), }; static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = { .hdr.src_addr = RTE_BE32(0xffffffff), .hdr.dst_addr = RTE_BE32(0xffffffff), .hdr.next_proto_id = 0xff, + .hdr.packet_id = 0xffff, + .hdr.fragment_offset = 0xffff, }; static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = { .hdr = { - .src_addr = RTE_IPV6_MASK_FULL, - .dst_addr = RTE_IPV6_MASK_FULL, + .src_addr = { + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + }, + .dst_addr = { + "\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff" + }, .proto = 0xff }, }; @@ -170,7 +210,12 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, + .vni = "\xff\xff\xff", +}; + +static const struct rte_flow_item_geneve dpaa2_flow_item_geneve_mask = { + .protocol = RTE_BE16(0xffff), + .vni = "\xff\xff\xff", }; static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { @@ -185,643 +230,606 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { }; static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { - .label_tc_s = { 0xff, 0xff, 0xff }, + .label_tc_s = {0xff, 0xff, 0xff}, }; static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .code = 0xff, .session_id = RTE_BE16(0xffff), }; - #endif - -#define DPAA2_FLOW_DUMP dpaa2_dump_print - -static inline void -dpaa2_prot_field_string(uint32_t prot, uint32_t field, - char *string) +static int +dpaa2_flow_attr_group_convert(struct dpaa2_dev_priv *priv, + const struct rte_flow_attr *c_attr, struct rte_flow_attr *attr) { - if (!dpaa2_flow_control_log) - return; + enum rte_dpaa2_flow_type group_type; + uint32_t group_id; - if (prot == NET_PROT_ETH) { - strcpy(string, "eth"); - if (field == NH_FLD_ETH_DA) - strcat(string, ".dst"); - else if (field == NH_FLD_ETH_SA) - strcat(string, ".src"); - else if (field == NH_FLD_ETH_TYPE) - strcat(string, ".type"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_VLAN) { - strcpy(string, "vlan"); - if (field == NH_FLD_VLAN_TCI) - strcat(string, ".tci"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_IP) { - strcpy(string, "ip"); - if (field == NH_FLD_IP_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_IP_DST) - strcat(string, ".dst"); - else if (field == NH_FLD_IP_PROTO) - strcat(string, ".proto"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_TCP) { - strcpy(string, "tcp"); - if (field == NH_FLD_TCP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_TCP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_UDP) { - strcpy(string, "udp"); - if (field == NH_FLD_UDP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_UDP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_ICMP) { - strcpy(string, "icmp"); - if (field == NH_FLD_ICMP_TYPE) - strcat(string, ".type"); - else if (field == NH_FLD_ICMP_CODE) - strcat(string, ".code"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_SCTP) { - strcpy(string, "sctp"); - if (field == NH_FLD_SCTP_PORT_SRC) - strcat(string, ".src"); - else if (field == NH_FLD_SCTP_PORT_DST) - strcat(string, ".dst"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_GRE) { - strcpy(string, "gre"); - if (field == NH_FLD_GRE_TYPE) - strcat(string, ".type"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_GTP) { - rte_strscpy(string, "gtp", DPAA2_PROT_FIELD_STRING_SIZE); - if (field == NH_FLD_GTP_TEID) - strcat(string, ".teid"); - else - strcat(string, ".unknown field"); - } else if (prot == NET_PROT_IPSEC_ESP) { - rte_strscpy(string, "esp", DPAA2_PROT_FIELD_STRING_SIZE); - if (field == NH_FLD_IPSEC_ESP_SPI) - strcat(string, ".spi"); - else if (field == NH_FLD_IPSEC_ESP_SEQUENCE_NUM) - strcat(string, ".seq"); - else - strcat(string, ".unknown field"); - } else { - sprintf(string, "unknown protocol(%d)", prot); + group_type = RTE_DPAA2_FLOW_GROUP_TYPE_GET(c_attr->group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(c_attr->group); + if (group_id >= priv->num_rx_tc) { + group_id = 0; + group_type = RTE_DPAA2_QOS_GROUP_FLOW; } + if (group_type > RTE_DPAA2_MIX_GROUP_FLOW) + return -EINVAL; + rte_memcpy(attr, c_attr, sizeof(struct rte_flow_attr)); + attr->group = group_id; + RTE_DPAA2_FLOW_GROUP_TYPE_SET(attr->group, group_type); + + return 0; } -static inline void -dpaa2_flow_qos_extracts_log(const struct dpaa2_dev_priv *priv) +static int +dpaa2_flow_extract_support(const uint8_t *mask_src, const uint8_t *mask_support, + uint8_t size) { - int idx; - char string[32]; - const struct dpkg_profile_cfg *dpkg = - &priv->extract.qos_key_extract.dpkg; - const struct dpkg_extract *extract; - enum dpkg_extract_type type; - enum net_prot prot; - uint32_t field; + uint8_t mask[64], i; - if (!dpaa2_flow_control_log) - return; + rte_memcpy(mask, mask_support, size); - DPAA2_FLOW_DUMP("QoS table: %d extracts\r\n", - dpkg->num_extracts); - for (idx = 0; idx < dpkg->num_extracts; idx++) { - extract = &dpkg->extracts[idx]; - type = extract->type; - if (type == DPKG_EXTRACT_FROM_HDR) { - prot = extract->extract.from_hdr.prot; - field = extract->extract.from_hdr.field; - dpaa2_prot_field_string(prot, field, - string); - } else if (type == DPKG_EXTRACT_FROM_DATA) { - sprintf(string, "raw offset/len: %d/%d", - extract->extract.from_data.offset, - extract->extract.from_data.size); - } else if (type == DPKG_EXTRACT_FROM_PARSE) { - sprintf(string, "parse offset/len: %d/%d", - extract->extract.from_parse.offset, - extract->extract.from_parse.size); - } - DPAA2_FLOW_DUMP("%s", string); - if ((idx + 1) < dpkg->num_extracts) - DPAA2_FLOW_DUMP(" / "); + for (i = 0; i < size; i++) + mask[i] = (mask[i] | mask_src[i]); + + if (memcmp(mask, mask_support, size)) { + dpaa2_dump_print("Unsupported extracts with mask:"); + dpaa2_dump_hex_print(mask, size); + return -ENOTSUP; } - DPAA2_FLOW_DUMP("\r\n"); + + return 0; } -static inline void -dpaa2_flow_fs_extracts_log(const struct dpaa2_dev_priv *priv, - int tc_id) -{ - int idx; - char string[32]; - const struct dpkg_profile_cfg *dpkg = - &priv->extract.tc_key_extract[tc_id].dpkg; - const struct dpkg_extract *extract; - enum dpkg_extract_type type; +#define DPAA2_FLOW_EXTRACT_MAX_FIELDS 8 +struct dpaa2_flow_proto_handle { + const char *name; + int (*cb)(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, + int *ecfg); + int (*tunnel)(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, + int *ecfg); + enum dpaa2_parser_protocol_id protocol_id; + enum dpaa2_parser_protocol_id tunnel_id; + enum rte_flow_item_type item_type; + const void *mask_support; + uint32_t hdr_size; + int force_psr; enum net_prot prot; - uint32_t field; - - if (!dpaa2_flow_control_log) - return; + uint8_t fields_num; + uint32_t fields[DPAA2_FLOW_EXTRACT_MAX_FIELDS]; + uint16_t field_offset[DPAA2_FLOW_EXTRACT_MAX_FIELDS]; + uint16_t field_size[DPAA2_FLOW_EXTRACT_MAX_FIELDS]; +}; - DPAA2_FLOW_DUMP("FS table: %d extracts in TC[%d]\r\n", - dpkg->num_extracts, tc_id); - for (idx = 0; idx < dpkg->num_extracts; idx++) { - extract = &dpkg->extracts[idx]; - type = extract->type; - if (type == DPKG_EXTRACT_FROM_HDR) { - prot = extract->extract.from_hdr.prot; - field = extract->extract.from_hdr.field; - dpaa2_prot_field_string(prot, field, - string); - } else if (type == DPKG_EXTRACT_FROM_DATA) { - sprintf(string, "raw offset/len: %d/%d", - extract->extract.from_data.offset, - extract->extract.from_data.size); - } else if (type == DPKG_EXTRACT_FROM_PARSE) { - sprintf(string, "parse offset/len: %d/%d", - extract->extract.from_parse.offset, - extract->extract.from_parse.size); - } - DPAA2_FLOW_DUMP("%s", string); - if ((idx + 1) < dpkg->num_extracts) - DPAA2_FLOW_DUMP(" / "); - } - DPAA2_FLOW_DUMP("\r\n"); +static inline struct dpaa2_flow_tbl_profile * +dpaa2_flow_table_profile(struct dpaa2_generic_flow *flow) +{ + if (flow->type == DPAA2_FLOW_QOS_TYPE) + return &flow->priv->flow_profile.qos_profile; + return &flow->priv->flow_profile.tc_profile[flow->tc_id]; } -static inline void -dpaa2_flow_qos_entry_log(const char *log_info, - const struct dpaa2_dev_flow *flow, int qos_index) +static inline struct dpaa2_key_profile * +dpaa2_flow_key_profile(struct dpaa2_generic_flow *flow) { - int idx; - uint8_t *key, *mask; + struct dpaa2_flow_tbl_profile *tbl_profile = dpaa2_flow_table_profile(flow); - if (!dpaa2_flow_control_log) - return; + return &tbl_profile->key_profile; +} - if (qos_index >= 0) { - DPAA2_FLOW_DUMP("%s QoS entry[%d](size %d/%d) for TC[%d]\r\n", - log_info, qos_index, flow->qos_rule_size, - flow->qos_rule.key_size, - flow->tc_id); - } else { - DPAA2_FLOW_DUMP("%s QoS entry(size %d/%d) for TC[%d]\r\n", - log_info, flow->qos_rule_size, - flow->qos_rule.key_size, - flow->tc_id); +static int +dpaa2_flow_l4_port_extract(const struct dpkg_extract *l4_port_search) +{ + if (l4_port_search->type != DPKG_EXTRACT_FROM_HDR) + return -ENXIO; + if (l4_port_search->extract.from_hdr.prot == NET_PROT_TCP) { + if (l4_port_search->extract.from_hdr.field == NH_FLD_TCP_PORT_SRC) + return DPAA2_L4_SRC_PORT; + if (l4_port_search->extract.from_hdr.field == NH_FLD_TCP_PORT_DST) + return DPAA2_L4_DST_PORT; + } else if (l4_port_search->extract.from_hdr.prot == NET_PROT_UDP) { + if (l4_port_search->extract.from_hdr.field == NH_FLD_UDP_PORT_SRC) + return DPAA2_L4_SRC_PORT; + if (l4_port_search->extract.from_hdr.field == NH_FLD_UDP_PORT_DST) + return DPAA2_L4_DST_PORT; + } else if (l4_port_search->extract.from_hdr.prot == NET_PROT_SCTP) { + if (l4_port_search->extract.from_hdr.field == NH_FLD_SCTP_PORT_SRC) + return DPAA2_L4_SRC_PORT; + if (l4_port_search->extract.from_hdr.field == NH_FLD_SCTP_PORT_DST) + return DPAA2_L4_DST_PORT; } - key = flow->qos_key_addr; - mask = flow->qos_mask_addr; + return -ENXIO; +} - DPAA2_FLOW_DUMP("key:\r\n"); - for (idx = 0; idx < flow->qos_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", key[idx]); +static inline struct dpaa2_generic_flow * +dpaa2_flow_generic_flow(struct dpaa2_dev_flow *dev_flow, + enum dpaa2_flow_dist_type type, uint8_t tc_id) +{ + if (type == DPAA2_FLOW_QOS_TYPE) + return dev_flow->qos_flow; + if (type == DPAA2_FLOW_FS_TYPE && dev_flow->fs_flow && + (dev_flow->fs_flow->tc_id == tc_id || tc_id >= MAX_TCS)) { + return dev_flow->fs_flow; + } + if (type == DPAA2_FLOW_RSS_TYPE && dev_flow->rss_flow && + (dev_flow->rss_flow->tc_id == tc_id || tc_id >= MAX_TCS)) { + return dev_flow->rss_flow; + } - DPAA2_FLOW_DUMP("\r\nmask:\r\n"); - for (idx = 0; idx < flow->qos_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", mask[idx]); - DPAA2_FLOW_DUMP("\r\n"); + return NULL; } -static inline void -dpaa2_flow_fs_entry_log(const char *log_info, - const struct dpaa2_dev_flow *flow) +static inline int +dpaa2_flow_extract_search(const struct dpaa2_key_profile *key_profile, + enum key_prot_type type, enum net_prot prot, uint32_t key_field) { - int idx; - uint8_t *key, *mask; + int extract_idx, l4_idx; + const struct key_prot_field *prot_field; + struct dpkg_extract l4_port_search; - if (!dpaa2_flow_control_log) - return; + prot_field = key_profile->prot_field; + for (extract_idx = 0; extract_idx < key_profile->dpkg.num_extracts; extract_idx++) { + if (type == DPAA2_NET_PROT_KEY && + prot_field[extract_idx].prot == prot && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + else if (type == DPAA2_FAF_KEY && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + else if (type == DPAA2_PR_KEY && + prot_field[extract_idx].key_field == key_field && + prot_field[extract_idx].type == type) + return extract_idx; + } - DPAA2_FLOW_DUMP("%s FS/TC entry[%d](size %d/%d) of TC[%d]\r\n", - log_info, flow->tc_index, - flow->fs_rule_size, flow->fs_rule.key_size, - flow->tc_id); + if (type != DPAA2_NET_PROT_KEY) + return -ENXIO; - key = flow->fs_key_addr; - mask = flow->fs_mask_addr; + l4_port_search.type = DPKG_EXTRACT_FROM_HDR; + l4_port_search.extract.from_hdr.prot = prot; + l4_port_search.extract.from_hdr.field = key_field; - DPAA2_FLOW_DUMP("key:\r\n"); - for (idx = 0; idx < flow->fs_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", key[idx]); + l4_idx = dpaa2_flow_l4_port_extract(&l4_port_search); + if (l4_idx < 0) + return -ENXIO; + if (key_profile->l4_port[l4_idx].present) + return key_profile->l4_port[l4_idx].extract_idx; - DPAA2_FLOW_DUMP("\r\nmask:\r\n"); - for (idx = 0; idx < flow->fs_rule_size; idx++) - DPAA2_FLOW_DUMP("%02x ", mask[idx]); - DPAA2_FLOW_DUMP("\r\n"); + return -ENXIO; } -static int -dpaa2_flow_ip_address_extract(enum net_prot prot, - uint32_t field) +static void +_dpaa2_flow_rule_insert_hole(struct dpaa2_generic_flow *flow, + int offset, int size) { - if (prot == NET_PROT_IPV4 && - (field == NH_FLD_IPV4_SRC_IP || - field == NH_FLD_IPV4_DST_IP)) - return true; - else if (prot == NET_PROT_IPV6 && - (field == NH_FLD_IPV6_SRC_IP || - field == NH_FLD_IPV6_DST_IP)) - return true; - else if (prot == NET_PROT_IP && - (field == NH_FLD_IP_SRC || - field == NH_FLD_IP_DST)) - return true; + uint8_t *src, *dst; + uint8_t move_len; - return false; + if (!flow->key_addr || !flow->mask_addr) + return; + if (offset < flow->rule_size) { + src = flow->key_addr + offset; + dst = src + size; + move_len = flow->rule_size - offset; + memmove(dst, src, move_len); + memset(src, 0, size); + + src = flow->mask_addr + offset; + dst = src + size; + memmove(dst, src, move_len); + memset(src, 0, size); + flow->rule_size += size; + } else { + flow->rule_size = offset + size; + } } -static int -dpaa2_flow_l4_src_port_extract(enum net_prot prot, - uint32_t field) +static void +dpaa2_flow_rule_insert_hole(struct dpaa2_generic_flow *curr, + int offset, int size) { - if (prot == NET_PROT_TCP && - field == NH_FLD_TCP_PORT_SRC) - return true; - else if (prot == NET_PROT_UDP && - field == NH_FLD_UDP_PORT_SRC) - return true; - else if (prot == NET_PROT_SCTP && - field == NH_FLD_SCTP_PORT_SRC) - return true; - - return false; -} + struct dpaa2_dev_priv *priv = curr->priv; + struct dpaa2_dev_flow *flow; + struct dpaa2_generic_flow *steering_flow; -static int -dpaa2_flow_l4_dst_port_extract(enum net_prot prot, - uint32_t field) -{ - if (prot == NET_PROT_TCP && - field == NH_FLD_TCP_PORT_DST) - return true; - else if (prot == NET_PROT_UDP && - field == NH_FLD_UDP_PORT_DST) - return true; - else if (prot == NET_PROT_SCTP && - field == NH_FLD_SCTP_PORT_DST) - return true; + if (curr) + _dpaa2_flow_rule_insert_hole(curr, offset, size); - return false; + flow = LIST_FIRST(&priv->flows); + while (flow) { + steering_flow = dpaa2_flow_generic_flow(flow, curr->type, curr->tc_id); + flow = LIST_NEXT(flow, next); + if (!steering_flow || (!steering_flow->ip_src && !steering_flow->ip_dst)) + continue; + _dpaa2_flow_rule_insert_hole(steering_flow, offset, size); + } } static int -dpaa2_flow_add_qos_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow) +dpaa2_flow_faf_advance(struct dpaa2_generic_flow *flow, + int faf_byte, int *insert_offset) { - uint16_t qos_index; - int ret; - struct fsl_mc_io *dpni = priv->hw; - - if (priv->num_rx_tc <= 1 && - flow->action_type != RTE_FLOW_ACTION_TYPE_RSS) { - DPAA2_PMD_WARN("No QoS Table for FS"); - return -EINVAL; - } + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + uint8_t idx, offset = 0xff; + struct key_prot_field prot = {0}; - /* QoS entry added is only effective for multiple TCs.*/ - qos_index = flow->tc_id * priv->fs_entries + flow->tc_index; - if (qos_index >= priv->qos_entries) { - DPAA2_PMD_ERR("QoS table full(%d >= %d)", - qos_index, priv->qos_entries); + if (key_profile->dpkg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { + DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - dpaa2_flow_qos_entry_log("Start add", flow, qos_index); - - ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, - priv->token, &flow->qos_rule, - flow->tc_id, qos_index, - 0, 0); - if (ret < 0) { - DPAA2_PMD_ERR("Add entry(%d) to table(%d) failed", - qos_index, flow->tc_id); - return ret; - } + prot.type = DPAA2_FAF_KEY; + prot.key_field = faf_byte; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + 1, &offset, insert_offset, &prot); + dpaa2_flow_rule_insert_hole(flow, offset, 1); - return 0; + return idx; } static int -dpaa2_flow_add_fs_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow) +dpaa2_flow_extract_add_faf_psr(struct dpaa2_generic_flow *flow, + int faf_byte, int *insert_offset) { - int ret; - struct fsl_mc_io *dpni = priv->hw; + int extract_idx; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + struct dpkg_extract extract; - if (flow->tc_index >= priv->fs_entries) { - DPAA2_PMD_ERR("FS table full(%d >= %d)", - flow->tc_index, priv->fs_entries); + if (key_profile->dpkg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { + DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - dpaa2_flow_fs_entry_log("Start add", flow); + extract_idx = dpaa2_flow_faf_advance(flow, faf_byte, insert_offset); + if (extract_idx < 0) + return extract_idx; - if (priv->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { - ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, - priv->token, flow->tc_id, - flow->tc_index, &flow->fs_rule, - &flow->fs_action_cfg); - } else { - ret = dpni_add_fs_entry_legacy(dpni, CMD_PRI_LOW, - priv->token, flow->tc_id, - flow->tc_index, &flow->fs_rule, - &flow->fs_action_cfg); - } - if (ret < 0) { - DPAA2_PMD_ERR("Add rule(%d) to FS table(%d) failed", - flow->tc_index, flow->tc_id); - return ret; - } + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_PARSE; + extract.extract.from_parse.offset = faf_byte; + extract.extract.from_parse.size = 1; + dpaa2_dpkg_insert_extract(&key_profile->dpkg, extract_idx, &extract); return 0; } +static inline int +dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile, + enum key_prot_type type, enum net_prot prot, uint32_t key_field) +{ + int i; + + i = dpaa2_flow_extract_search(key_profile, type, prot, key_field); + if (i >= 0) + return key_profile->prot_field[i].key_offset; + else + return i; +} + static int -dpaa2_flow_rule_insert_hole(struct dpaa2_dev_flow *flow, - int offset, int size, - enum dpaa2_flow_dist_type dist_type) +dpaa2_flow_faf_add_rule(struct dpaa2_generic_flow *flow, uint32_t faf_bit_off) { - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - if (offset < flow->qos_rule_size) { - memmove(flow->qos_key_addr + offset + size, - flow->qos_key_addr + offset, - flow->qos_rule_size - offset); - memset(flow->qos_key_addr + offset, - 0, size); - - memmove(flow->qos_mask_addr + offset + size, - flow->qos_mask_addr + offset, - flow->qos_rule_size - offset); - memset(flow->qos_mask_addr + offset, - 0, size); - flow->qos_rule_size += size; - } else { - flow->qos_rule_size = offset + size; - } - } + int offset; + uint8_t *key_addr, *mask_addr; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + uint8_t faf_byte = faf_bit_off / 8; + uint8_t faf_bit_in_byte = faf_bit_off % 8; - if (dist_type & DPAA2_FLOW_FS_TYPE) { - if (offset < flow->fs_rule_size) { - memmove(flow->fs_key_addr + offset + size, - flow->fs_key_addr + offset, - flow->fs_rule_size - offset); - memset(flow->fs_key_addr + offset, - 0, size); - - memmove(flow->fs_mask_addr + offset + size, - flow->fs_mask_addr + offset, - flow->fs_rule_size - offset); - memset(flow->fs_mask_addr + offset, - 0, size); - flow->fs_rule_size += size; - } else { - flow->fs_rule_size = offset + size; - } + faf_bit_in_byte = 7 - faf_bit_in_byte; + offset = dpaa2_flow_extract_key_offset(key_profile, + DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); + if (offset < 0) { + DPAA2_PMD_ERR("Failed(%d) to extract FAF offset", offset); + return offset; } + if (!flow->key_addr || !flow->mask_addr) + return 0; + + key_addr = flow->key_addr + offset; + mask_addr = flow->mask_addr + offset; + + if (!(*key_addr) && !(flow->ip_src || flow->ip_dst) && + offset >= flow->rule_size) + flow->rule_size = offset + sizeof(uint8_t); + + *key_addr |= (1 << faf_bit_in_byte); + *mask_addr |= (1 << faf_bit_in_byte); return 0; } static int -dpaa2_flow_rule_add_all(struct dpaa2_dev_priv *priv, - enum dpaa2_flow_dist_type dist_type, - uint16_t entry_size, uint8_t tc_id) +dpaa2_flow_identify_by_faf(struct dpaa2_generic_flow *flow, + uint32_t faf_bit_off, int *recfg) { - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - int ret; + int ret, index; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + uint8_t faf_byte = faf_bit_off / 8; - while (curr) { - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - if (priv->num_rx_tc > 1 || - curr->action_type == - RTE_FLOW_ACTION_TYPE_RSS) { - curr->qos_rule.key_size = entry_size; - ret = dpaa2_flow_add_qos_rule(priv, curr); - if (ret) - return ret; - } - } - if (dist_type & DPAA2_FLOW_FS_TYPE && - curr->tc_id == tc_id) { - curr->fs_rule.key_size = entry_size; - ret = dpaa2_flow_add_fs_rule(priv, curr); - if (ret) - return ret; + index = dpaa2_flow_extract_search(key_profile, DPAA2_FAF_KEY, + NET_PROT_NONE, faf_byte); + if (index < 0) { + ret = dpaa2_flow_extract_add_faf_psr(flow, faf_byte, NULL); + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to add %s faf extract", + ret, flow->type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "TC"); + + return ret; } - curr = LIST_NEXT(curr, next); + if (recfg) + *recfg = true; + } + ret = dpaa2_flow_faf_add_rule(flow, faf_bit_off); + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to add %s faf rule", + ret, flow->type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "TC"); + return ret; } return 0; } static int -dpaa2_flow_qos_rule_insert_hole(struct dpaa2_dev_priv *priv, - int offset, int size) +dpaa2_flow_general_tunnel_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) { - struct dpaa2_dev_flow *curr; - int ret; + int ret = 0; + uint32_t bit_offset; - curr = priv->curr; - if (!curr) { - DPAA2_PMD_ERR("Current qos flow insert hole failed."); - return -EINVAL; - } else { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; + if (pattern->spec) { + DPAA2_PMD_ERR("Tunnel distribution not support"); + return -ENOTSUP; } - curr = LIST_FIRST(&priv->flows); - while (curr) { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - curr = LIST_NEXT(curr, next); - } + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, hd->tunnel_id); + if (ret) + return ret; - return 0; + return dpaa2_flow_identify_by_faf(flow, bit_offset, ecfg); } static int -dpaa2_flow_fs_rule_insert_hole(struct dpaa2_dev_priv *priv, - int offset, int size, int tc_id) +dpaa2_flow_soft_psr_advance(struct dpaa2_generic_flow *flow, + uint32_t pr_offset, uint32_t pr_size, int *insert_offset) { - struct dpaa2_dev_flow *curr; - int ret; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + uint8_t idx, offset = 0xff; + struct key_prot_field prot = {0}; - curr = priv->curr; - if (!curr || curr->tc_id != tc_id) { - DPAA2_PMD_ERR("Current flow insert hole failed."); + if (key_profile->dpkg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { + DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; - } else { - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; } - curr = LIST_FIRST(&priv->flows); - - while (curr) { - if (curr->tc_id != tc_id) { - curr = LIST_NEXT(curr, next); - continue; - } - ret = dpaa2_flow_rule_insert_hole(curr, offset, size, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - curr = LIST_NEXT(curr, next); - } + prot.type = DPAA2_PR_KEY; + prot.key_field = (pr_offset << 16) | pr_size; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + pr_size, &offset, insert_offset, &prot); + dpaa2_flow_rule_insert_hole(flow, offset, pr_size); - return 0; + return idx; } static int -dpaa2_flow_faf_advance(struct dpaa2_dev_priv *priv, - int faf_byte, enum dpaa2_flow_dist_type dist_type, int tc_id, - int *insert_offset) +dpaa2_flow_extract_add_soft_psr(struct dpaa2_generic_flow *flow, + uint32_t pr_offset, uint32_t pr_size, int *insert_offset) { - int offset, ret; - struct dpaa2_key_profile *key_profile; - int num, pos; + int extract_idx; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + struct dpkg_extract extract; - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; - else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - - num = key_profile->num; + if ((pr_offset + pr_size) > DPAA2_PSR_RESULT_SIZE) { + DPAA2_PMD_ERR("PR extracts(%d:%d) overflow", + pr_offset, pr_size); + return -EINVAL; + } - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->dpkg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off++; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, 1); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, 1, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } + extract_idx = dpaa2_flow_soft_psr_advance(flow, pr_offset, pr_size, insert_offset); + if (extract_idx < 0) + return extract_idx; - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_PARSE; + extract.extract.from_parse.offset = pr_offset; + extract.extract.from_parse.size = pr_size; + dpaa2_dpkg_insert_extract(&key_profile->dpkg, extract_idx, &extract); - key_profile->key_size[pos] = 1; - key_profile->prot_field[pos].type = DPAA2_FAF_KEY; - key_profile->prot_field[pos].key_field = faf_byte; - key_profile->num++; + return 0; +} - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; +static inline int +dpaa2_flow_pr_rule_data_set(struct dpaa2_generic_flow *flow, + uint32_t pr_offset, uint32_t pr_size, const void *key, const void *mask, + enum dpaa2_flow_dist_type dist_type) +{ + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + int offset; + uint32_t pr_field = pr_offset << 16 | pr_size; + char offset_info[64], size_info[64], rule_size_info[64]; - key_profile->key_max_size++; + offset = dpaa2_flow_extract_key_offset(key_profile, + DPAA2_PR_KEY, NET_PROT_NONE, pr_field); + if (offset < 0) { + DPAA2_PMD_ERR("PR off(%d)/size(%d) does not exist!", + pr_offset, pr_size); + return offset; + } + snprintf(offset_info, 64, "offset(%d)", offset); + snprintf(size_info, 64, "size(%d)", pr_size); + + snprintf(rule_size_info, 64, "%s rule size(%d)", + dist_type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", flow->rule_size); + memcpy((flow->key_addr + offset), key, pr_size); + memcpy((flow->mask_addr + offset), mask, pr_size); + if (!(flow->ip_src || flow->ip_dst)) { + if (offset >= flow->rule_size) { + flow->rule_size = offset + pr_size; + } else if ((offset + pr_size) > flow->rule_size) { + DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", + offset_info, rule_size_info, + offset_info, size_info, + rule_size_info); + return -EINVAL; + } + } - return pos; + return 0; } static int -dpaa2_flow_pr_advance(struct dpaa2_dev_priv *priv, - uint32_t pr_offset, uint32_t pr_size, - enum dpaa2_flow_dist_type dist_type, int tc_id, - int *insert_offset) +dpaa2_flow_add_soft_psr_extract_rule(struct dpaa2_generic_flow *flow, + uint32_t pr_offset, uint32_t pr_size, const void *key, + const void *mask, int *recfg) { - int offset, ret; - struct dpaa2_key_profile *key_profile; - int num, pos; + int index, ret; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + uint32_t pr_field = pr_offset << 16 | pr_size; - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; - else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; + index = dpaa2_flow_extract_search(key_profile, DPAA2_PR_KEY, NET_PROT_NONE, pr_field); + if (index < 0) { + ret = dpaa2_flow_extract_add_soft_psr(flow, pr_offset, pr_size, NULL); + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to add off(%d)/size(%d) of PSR", + ret, pr_offset, pr_size); - num = key_profile->num; + return ret; + } + if (recfg) + *recfg = true; + } - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { - DPAA2_PMD_ERR("Number of extracts overflows"); - return -EINVAL; + if (!flow->key_addr || !flow->mask_addr) + return 0; + + return dpaa2_flow_pr_rule_data_set(flow, pr_offset, pr_size, key, mask, flow->type); +} + +static int +dpaa2_flow_tunnel_eth_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) +{ + int ret; + uint32_t i; + const struct rte_flow_item_eth *spec, *mask; + const void *_mask; + const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; + const uint32_t src_eth_offset[] = { + DPAA2_VXLAN_IN_SADDR0_OFFSET, + DPAA2_VXLAN_IN_SADDR1_OFFSET, + DPAA2_VXLAN_IN_SADDR2_OFFSET, + DPAA2_VXLAN_IN_SADDR3_OFFSET, + DPAA2_VXLAN_IN_SADDR4_OFFSET, + DPAA2_VXLAN_IN_SADDR5_OFFSET + }; + const uint32_t dst_eth_offset[] = { + DPAA2_VXLAN_IN_DADDR0_OFFSET, + DPAA2_VXLAN_IN_DADDR1_OFFSET, + DPAA2_VXLAN_IN_DADDR2_OFFSET, + DPAA2_VXLAN_IN_DADDR3_OFFSET, + DPAA2_VXLAN_IN_DADDR4_OFFSET, + DPAA2_VXLAN_IN_DADDR5_OFFSET + }; + + if (!pattern->spec) + return 0; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? pattern->mask : hd->mask_support; + _mask = mask; + + ret = dpaa2_flow_extract_support(_mask, hd->mask_support, hd->hdr_size); + if (ret) + return ret; + + if (memcmp((const char *)&mask->src, zero_cmp, RTE_ETHER_ADDR_LEN)) { + for (i = 0; i < RTE_DIM(src_eth_offset); i++) { + ret = dpaa2_flow_add_soft_psr_extract_rule(flow, + src_eth_offset[i], 1, &spec->src.addr_bytes[i], + &mask->src.addr_bytes[i], ecfg); + if (ret) + return ret; + } } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off += pr_size; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, pr_size); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, pr_size, tc_id); + if (memcmp((const char *)&mask->dst, zero_cmp, RTE_ETHER_ADDR_LEN)) { + for (i = 0; i < RTE_DIM(dst_eth_offset); i++) { + ret = dpaa2_flow_add_soft_psr_extract_rule(flow, + dst_eth_offset[i], 1, &spec->dst.addr_bytes[i], + &mask->dst.addr_bytes[i], ecfg); + if (ret) + return ret; } + } + + if (memcmp((const char *)&mask->type, zero_cmp, sizeof(rte_be16_t))) { + ret = dpaa2_flow_add_soft_psr_extract_rule(flow, + DPAA2_VXLAN_IN_TYPE_OFFSET, sizeof(rte_be16_t), + &spec->type, &mask->type, ecfg); if (ret) return ret; - } else { - pos = num; } - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; + return 0; +} + +static int +dpaa2_flow_tunnel_vlan_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) +{ + int ret; + const struct rte_flow_item_vlan *spec, *mask; + const void *_mask; + uint32_t bit_offset; + + spec = pattern->spec; + mask = pattern->mask ? pattern->mask : hd->mask_support; + _mask = mask; + + if (!spec) { + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, hd->tunnel_id); + if (ret) + return ret; + + return dpaa2_flow_identify_by_faf(flow, bit_offset, ecfg); } - key_profile->key_size[pos] = pr_size; - key_profile->prot_field[pos].type = DPAA2_PR_KEY; - key_profile->prot_field[pos].key_field = - (pr_offset << 16) | pr_size; - key_profile->num++; + ret = dpaa2_flow_extract_support(_mask, hd->mask_support, hd->hdr_size); + if (ret) + return ret; - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; + if (!mask->tci) + return 0; - key_profile->key_max_size += pr_size; + return dpaa2_flow_add_soft_psr_extract_rule(flow, + DPAA2_VXLAN_IN_TCI_OFFSET, sizeof(rte_be16_t), + &spec->tci, &mask->tci, ecfg); +} - return pos; +static int +dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_generic_flow *flow, + enum net_prot prot, uint32_t field, + const void *key, const void *mask, int size, int *recfg) +{ + return dpaa2_profile_insert_ipaddr_extract(dpaa2_flow_key_profile(flow), + prot, field, flow->key_addr, flow->mask_addr, key, mask, size, + &flow->rule_size, recfg); } /* Move IPv4/IPv6 addresses to fill new extract previous IP address. @@ -830,262 +838,154 @@ dpaa2_flow_pr_advance(struct dpaa2_dev_priv *priv, * the extracts position following them can't be identified. */ static int -dpaa2_flow_key_profile_advance(enum net_prot prot, - uint32_t field, uint8_t field_size, - struct dpaa2_dev_priv *priv, - enum dpaa2_flow_dist_type dist_type, int tc_id, - int *insert_offset) +dpaa2_flow_key_profile_advance(struct dpaa2_generic_flow *flow, + enum net_prot prot, uint32_t field, uint8_t field_size, int *insert_offset) { - int offset, ret; - struct dpaa2_key_profile *key_profile; - int num, pos; - - if (dpaa2_flow_ip_address_extract(prot, field)) { - DPAA2_PMD_ERR("%s only for none IP address extract", - __func__); - return -EINVAL; - } - - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_profile = &priv->extract.qos_key_extract.key_profile; - else - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - - num = key_profile->num; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + struct dpkg_extract l4_port_search; + uint8_t idx, offset = 0xff; + int l4_idx; + struct key_prot_field prot_field; - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->dpkg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - offset = key_profile->ip_addr_extract_off; - pos = key_profile->ip_addr_extract_pos; - key_profile->ip_addr_extract_pos++; - key_profile->ip_addr_extract_off += field_size; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - offset, field_size); - } else { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - offset, field_size, tc_id); - } - if (ret) - return ret; - } else { - pos = num; - } - - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - - key_profile->key_size[pos] = field_size; - key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY; - key_profile->prot_field[pos].prot = prot; - key_profile->prot_field[pos].key_field = field; - key_profile->num++; + prot_field.type = DPAA2_NET_PROT_KEY; + prot_field.prot = prot; + prot_field.key_field = field; + idx = dpaa2_profile_insert_no_ipaddr_extract(key_profile, + field_size, &offset, insert_offset, &prot_field); + if (offset != 0xff) + dpaa2_flow_rule_insert_hole(flow, offset, field_size); - if (insert_offset) - *insert_offset = key_profile->key_offset[pos]; - - if (dpaa2_flow_l4_src_port_extract(prot, field)) { - key_profile->l4_src_port_present = 1; - key_profile->l4_src_port_pos = pos; - key_profile->l4_src_port_offset = - key_profile->key_offset[pos]; - } else if (dpaa2_flow_l4_dst_port_extract(prot, field)) { - key_profile->l4_dst_port_present = 1; - key_profile->l4_dst_port_pos = pos; - key_profile->l4_dst_port_offset = - key_profile->key_offset[pos]; + l4_port_search.type = DPKG_EXTRACT_FROM_HDR; + l4_port_search.extract.from_hdr.prot = prot; + l4_port_search.extract.from_hdr.field = field; + l4_idx = dpaa2_flow_l4_port_extract(&l4_port_search); + if (l4_idx >= 0) { + key_profile->l4_port[l4_idx].present = true; + key_profile->l4_port[l4_idx].extract_idx = idx; + key_profile->l4_port[l4_idx].key_offset = key_profile->prot_field[idx].key_offset; } - key_profile->key_max_size += field_size; - return pos; + return idx; } static int -dpaa2_flow_faf_add_hdr(int faf_byte, - struct dpaa2_dev_priv *priv, - enum dpaa2_flow_dist_type dist_type, int tc_id, - int *insert_offset) +dpaa2_flow_extract_add_hdr(struct dpaa2_generic_flow *flow, + enum net_prot prot, uint32_t field, uint8_t field_size, int *insert_offset) { - int pos, i, offset; - struct dpaa2_key_extract *key_extract; - struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; - else - key_extract = &priv->extract.tc_key_extract[tc_id]; - - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + int extract_idx; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + struct dpkg_extract extract; - if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { + if (key_profile->dpkg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { DPAA2_PMD_ERR("Number of extracts overflows"); return -EINVAL; } - pos = dpaa2_flow_faf_advance(priv, - faf_byte, dist_type, tc_id, - insert_offset); - if (pos < 0) - return pos; - - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } - } - - offset = DPAA2_FAFE_PSR_OFFSET + faf_byte; + extract_idx = dpaa2_flow_key_profile_advance(flow, prot, + field, field_size, insert_offset); + if (extract_idx < 0) + return extract_idx; - extracts[pos].type = DPKG_EXTRACT_FROM_PARSE; - extracts[pos].extract.from_parse.offset = offset; - extracts[pos].extract.from_parse.size = 1; - - dpkg->num_extracts++; + memset(&extract, 0, sizeof(extract)); + extract.type = DPKG_EXTRACT_FROM_HDR; + extract.extract.from_hdr.prot = prot; + extract.extract.from_hdr.type = DPKG_FULL_FIELD; + extract.extract.from_hdr.field = field; + dpaa2_dpkg_insert_extract(&key_profile->dpkg, extract_idx, &extract); return 0; } -static int -dpaa2_flow_pr_add_hdr(uint32_t pr_offset, - uint32_t pr_size, struct dpaa2_dev_priv *priv, - enum dpaa2_flow_dist_type dist_type, int tc_id, - int *insert_offset) +static inline int +dpaa2_flow_hdr_rule_data_set(struct dpaa2_generic_flow *flow, + enum net_prot prot, uint32_t field, int size, + const void *key, const void *mask) { - int pos, i; - struct dpaa2_key_extract *key_extract; - struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + int offset, i; + char offset_info[64], size_info[64], rule_size_info[64]; - if ((pr_offset + pr_size) > DPAA2_FAPR_SIZE) { - DPAA2_PMD_ERR("PR extracts(%d:%d) overflow", - pr_offset, pr_size); + offset = dpaa2_flow_extract_key_offset(key_profile, + DPAA2_NET_PROT_KEY, prot, field); + if (offset < 0) { + DPAA2_PMD_ERR("P(%d)/F(%d) does not exist!", + prot, field); return -EINVAL; } + snprintf(offset_info, 64, "offset(%d)", offset); + snprintf(size_info, 64, "size(%d)", size); - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; - else - key_extract = &priv->extract.tc_key_extract[tc_id]; - - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + snprintf(rule_size_info, 64, "%s rule size(%d)", + flow->type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", + flow->rule_size); - if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { - DPAA2_PMD_ERR("Number of extracts overflows"); - return -EINVAL; + for (i = 0; i < size; i++) { + *(flow->key_addr + offset + i) |= *((const uint8_t *)key + i); + *(flow->mask_addr + offset + i) |= *((const uint8_t *)mask + i); } - - pos = dpaa2_flow_pr_advance(priv, - pr_offset, pr_size, dist_type, tc_id, - insert_offset); - if (pos < 0) - return pos; - - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; + if (!(flow->ip_src || flow->ip_dst)) { + if (offset >= flow->rule_size) { + flow->rule_size = offset + size; + } else if ((offset + size) > flow->rule_size) { + DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", + __func__, offset_info, rule_size_info, + offset_info, size_info, rule_size_info); + return -EINVAL; } } - extracts[pos].type = DPKG_EXTRACT_FROM_PARSE; - extracts[pos].extract.from_parse.offset = pr_offset; - extracts[pos].extract.from_parse.size = pr_size; - - dpkg->num_extracts++; - return 0; } static int -dpaa2_flow_extract_add_hdr(enum net_prot prot, - uint32_t field, uint8_t field_size, - struct dpaa2_dev_priv *priv, - enum dpaa2_flow_dist_type dist_type, int tc_id, - int *insert_offset) +dpaa2_flow_add_hdr_extract_rule(struct dpaa2_generic_flow *flow, + enum net_prot prot, uint32_t field, + const void *key, const void *mask, int size, int *recfg) { - int pos, i; - struct dpaa2_key_extract *key_extract; - struct dpkg_profile_cfg *dpkg; - struct dpkg_extract *extracts; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; - else - key_extract = &priv->extract.tc_key_extract[tc_id]; + int index, ret = 0; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); - dpkg = &key_extract->dpkg; - extracts = dpkg->extracts; + index = dpaa2_flow_extract_search(key_profile, DPAA2_NET_PROT_KEY, prot, field); + if (index < 0) { + ret = dpaa2_flow_extract_add_hdr(flow, prot, field, size, NULL); + if (ret) { + DPAA2_PMD_ERR("QoS Extract P(%d)/F(%d) failed", prot, field); - if (dpaa2_flow_ip_address_extract(prot, field)) { - DPAA2_PMD_ERR("%s only for none IP address extract", - __func__); - return -EINVAL; + return ret; + } + if (recfg) + (*recfg) = true; } - if (dpkg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { - DPAA2_PMD_ERR("Number of extracts overflows"); - return -EINVAL; + if (!flow->key_addr || !flow->mask_addr) { + /** None steering flow, no rule data specified.*/ + return 0; } - pos = dpaa2_flow_key_profile_advance(prot, - field, field_size, priv, - dist_type, tc_id, - insert_offset); - if (pos < 0) - return pos; - - if (pos != dpkg->num_extracts) { - /* Not the last pos, must have IP address extract.*/ - for (i = dpkg->num_extracts - 1; i >= pos; i--) { - extracts[i + 1] = extracts[i]; - } + ret = dpaa2_flow_hdr_rule_data_set(flow, prot, field, size, key, mask); + if (ret) { + DPAA2_PMD_ERR("%s P(%d)/F(%d) rule data set failed", + flow->type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", + prot, field); } - extracts[pos].type = DPKG_EXTRACT_FROM_HDR; - extracts[pos].extract.from_hdr.prot = prot; - extracts[pos].extract.from_hdr.type = DPKG_FULL_FIELD; - extracts[pos].extract.from_hdr.field = field; - - dpkg->num_extracts++; - - return 0; + return ret; } static int -dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, - int offset, int size, - enum dpaa2_flow_dist_type dist_type, int tc_id) +_dpaa2_flow_extract_add_raw(struct dpaa2_generic_flow *flow, + int offset, int size) { - struct dpaa2_key_extract *key_extract; - struct dpkg_profile_cfg *dpkg; - struct dpaa2_key_profile *key_profile; - int last_extract_size, index, pos, item_size; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + int last_extract_size, index, raw_idx, item_size; uint8_t num_extracts; uint32_t field; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; - else - key_extract = &priv->extract.tc_key_extract[tc_id]; - - dpkg = &key_extract->dpkg; - key_profile = &key_extract->key_profile; - - key_profile->raw_region.raw_start = 0; - key_profile->raw_region.raw_size = 0; + int ret; last_extract_size = (size % DPAA2_FLOW_MAX_KEY_SIZE); num_extracts = (size / DPAA2_FLOW_MAX_KEY_SIZE); @@ -1094,6 +994,11 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, else last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE; + if ((key_profile->dpkg.num_extracts + num_extracts) > DPKG_MAX_NUM_OF_EXTRACTS) { + DPAA2_PMD_ERR("Failed to expand raw extracts"); + return -EINVAL; + } + for (index = 0; index < num_extracts; index++) { if (index == num_extracts - 1) item_size = last_extract_size; @@ -1102,531 +1007,366 @@ dpaa2_flow_extract_new_raw(struct dpaa2_dev_priv *priv, field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; field |= item_size; - pos = dpaa2_flow_key_profile_advance(NET_PROT_PAYLOAD, - field, item_size, priv, dist_type, - tc_id, NULL); - if (pos < 0) - return pos; - - dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA; - dpkg->extracts[pos].extract.from_data.size = item_size; - dpkg->extracts[pos].extract.from_data.offset = offset; - - if (index == 0) { - key_profile->raw_extract_pos = pos; - key_profile->raw_extract_off = - key_profile->key_offset[pos]; - key_profile->raw_region.raw_start = offset; + ret = dpaa2_flow_extract_search(key_profile, + DPAA2_NET_PROT_KEY, NET_PROT_PAYLOAD, field); + if (ret >= 0) { + offset += item_size; + continue; } - key_profile->raw_extract_num++; - key_profile->raw_region.raw_size += - key_profile->key_size[pos]; + + raw_idx = dpaa2_flow_key_profile_advance(flow, NET_PROT_PAYLOAD, + field, item_size, NULL); + if (raw_idx < 0) + return raw_idx; + + key_profile->dpkg.extracts[raw_idx].type = DPKG_EXTRACT_FROM_DATA; + key_profile->dpkg.extracts[raw_idx].extract.from_data.size = item_size; + key_profile->dpkg.extracts[raw_idx].extract.from_data.offset = offset; offset += item_size; - dpkg->num_extracts++; + key_profile->dpkg.num_extracts++; } return 0; } static int -dpaa2_flow_extract_add_raw(struct dpaa2_dev_priv *priv, - int offset, int size, enum dpaa2_flow_dist_type dist_type, - int tc_id, int *recfg) +dpaa2_flow_extract_add_raw(struct dpaa2_generic_flow *flow, + int offset, int size, int *recfg) { - struct dpaa2_key_profile *key_profile; - struct dpaa2_raw_region *raw_region; - int end = offset + size, ret = 0, extract_extended, sz_extend; - int start_cmp, end_cmp, new_size, index, pos, end_pos; - int last_extract_size, item_size, num_extracts, bk_num = 0; - struct dpkg_extract extract_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - uint8_t key_offset_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - uint8_t key_size_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - struct key_prot_field prot_field_bk[DPKG_MAX_NUM_OF_EXTRACTS]; - struct dpaa2_raw_region raw_hole; - struct dpkg_profile_cfg *dpkg; - enum net_prot prot; - uint32_t field; + int ret; - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - key_profile = &priv->extract.qos_key_extract.key_profile; - dpkg = &priv->extract.qos_key_extract.dpkg; + ret = _dpaa2_flow_extract_add_raw(flow, offset, size); + if (!ret && recfg) + (*recfg) |= true; + + return ret; +} + +static int +dpaa2_flow_ip_fields_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct dpaa2_flow_proto_handle *hd, uint8_t idx, + const uint8_t *spec_u8, const uint8_t *mask_u8, int *ecfg) +{ + int ret; + uint32_t bit_offset; + const char zero_cmp[128] = {0}; + const uint8_t ipv4_src_offset = offsetof(struct rte_flow_item_ipv4, hdr.src_addr); + const uint8_t ipv4_dst_offset = offsetof(struct rte_flow_item_ipv4, hdr.dst_addr); + const uint8_t ipv6_src_offset = offsetof(struct rte_flow_item_ipv6, hdr.src_addr); + const uint8_t ipv6_dst_offset = offsetof(struct rte_flow_item_ipv6, hdr.dst_addr); + const uint8_t ipv4_frag_offset = offsetof(struct rte_flow_item_ipv4, hdr.fragment_offset); + + if ((hd->item_type == RTE_FLOW_ITEM_TYPE_IPV4 && + (hd->field_offset[idx] == ipv4_src_offset || + hd->field_offset[idx] == ipv4_dst_offset)) || + (hd->item_type == RTE_FLOW_ITEM_TYPE_IPV6 && + (hd->field_offset[idx] == ipv6_src_offset || + hd->field_offset[idx] == ipv6_dst_offset))) { + ret = dpaa2_flow_add_ipaddr_extract_rule(flow, hd->prot, hd->fields[idx], + spec_u8 + hd->field_offset[idx], mask_u8 + hd->field_offset[idx], + hd->field_size[idx], ecfg); + if (ret) + return ret; + if ((hd->item_type == RTE_FLOW_ITEM_TYPE_IPV4 && + hd->field_offset[idx] == ipv4_src_offset) || + (hd->item_type == RTE_FLOW_ITEM_TYPE_IPV6 && + hd->field_offset[idx] == ipv6_src_offset)) + flow->ip_src = NET_PROT_IPV4; + else + flow->ip_dst = NET_PROT_IPV4; + } else if (hd->item_type == RTE_FLOW_ITEM_TYPE_IPV4 && + hd->field_offset[idx] == ipv4_frag_offset) { + if (memcmp(spec_u8 + hd->field_offset[idx], zero_cmp, hd->field_size[idx])) + DPAA2_PMD_WARN("Unsupport Extract of frag offset"); + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, DPAA2_PARSER_IP_FRAG_ID); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(flow, bit_offset, ecfg); + if (ret) + return ret; } else { - key_profile = &priv->extract.tc_key_extract[tc_id].key_profile; - dpkg = &priv->extract.tc_key_extract[tc_id].dpkg; + ret = dpaa2_flow_add_hdr_extract_rule(flow, hd->prot, + hd->fields[idx], spec_u8 + hd->field_offset[idx], + mask_u8 + hd->field_offset[idx], hd->field_size[idx], ecfg); + if (ret) + return ret; } - raw_region = &key_profile->raw_region; - if (!raw_region->raw_size) { - /* New RAW region*/ - ret = dpaa2_flow_extract_new_raw(priv, offset, size, - dist_type, tc_id); - if (!ret && recfg) - (*recfg) |= dist_type; + return 0; +} + +static int +dpaa2_flow_ip_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) +{ + int ret, i; + uint32_t bit_offset; + const void *spec, *mask; + const uint8_t *mask_u8; + const char zero_cmp[128] = {0}; + + spec = pattern->spec; + mask = pattern->mask ? pattern->mask : hd->mask_support; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, hd->protocol_id); + if (ret) return ret; - } - start_cmp = raw_region->raw_start; - end_cmp = raw_region->raw_start + raw_region->raw_size; - if (offset >= start_cmp && end <= end_cmp) - return 0; + ret = dpaa2_flow_identify_by_faf(flow, bit_offset, ecfg); + if (ret) + return ret; - sz_extend = 0; - new_size = raw_region->raw_size; - if (offset < start_cmp) { - sz_extend += start_cmp - offset; - new_size += (start_cmp - offset); - } - if (end > end_cmp) { - sz_extend += end - end_cmp; - new_size += (end - end_cmp); - } + if (!spec) + goto skip_parse_spec; - last_extract_size = (new_size % DPAA2_FLOW_MAX_KEY_SIZE); - num_extracts = (new_size / DPAA2_FLOW_MAX_KEY_SIZE); - if (last_extract_size) - num_extracts++; - else - last_extract_size = DPAA2_FLOW_MAX_KEY_SIZE; + ret = dpaa2_flow_extract_support(mask, hd->mask_support, hd->hdr_size); + if (ret) + return ret; - if ((key_profile->num + num_extracts - - key_profile->raw_extract_num) >= - DPKG_MAX_NUM_OF_EXTRACTS) { - DPAA2_PMD_ERR("%s Failed to expand raw extracts", - __func__); - return -EINVAL; + mask_u8 = mask; + for (i = 0; i < hd->fields_num; i++) { + if (!memcmp(mask_u8 + hd->field_offset[i], zero_cmp, hd->field_size[i])) + continue; + ret = dpaa2_flow_ip_fields_extract_rule_set(flow, hd, i, spec, mask, ecfg); + if (ret) + return ret; } - if (offset < start_cmp) { - raw_hole.raw_start = key_profile->raw_extract_off; - raw_hole.raw_size = start_cmp - offset; - raw_region->raw_start = offset; - raw_region->raw_size += start_cmp - offset; +skip_parse_spec: + if (hd->item_type == RTE_FLOW_ITEM_TYPE_IPV4) + flow->ip_key = NET_PROT_IPV4; + else + flow->ip_key = NET_PROT_IPV6; - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size); - if (ret) - return ret; - } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size, tc_id); - if (ret) - return ret; - } - } + return 0; +} - if (end > end_cmp) { - raw_hole.raw_start = - key_profile->raw_extract_off + - raw_region->raw_size; - raw_hole.raw_size = end - end_cmp; - raw_region->raw_size += end - end_cmp; +static int +dpaa2_flow_vxlan_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) +{ + int ret; + uint32_t bit_offset; + const struct rte_flow_item_vxlan *spec, *mask; + const void *_mask; + struct dpaa2_dev_priv *priv = flow->priv; - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_flow_qos_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size); - if (ret) - return ret; - } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_flow_fs_rule_insert_hole(priv, - raw_hole.raw_start, - raw_hole.raw_size, tc_id); - if (ret) - return ret; - } - } + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? pattern->mask : hd->mask_support; + _mask = mask; - end_pos = key_profile->raw_extract_pos + - key_profile->raw_extract_num; - if (key_profile->num > end_pos) { - bk_num = key_profile->num - end_pos; - memcpy(extract_bk, &dpkg->extracts[end_pos], - bk_num * sizeof(struct dpkg_extract)); - memcpy(key_offset_bk, &key_profile->key_offset[end_pos], - bk_num * sizeof(uint8_t)); - memcpy(key_size_bk, &key_profile->key_size[end_pos], - bk_num * sizeof(uint8_t)); - memcpy(prot_field_bk, &key_profile->prot_field[end_pos], - bk_num * sizeof(struct key_prot_field)); - - for (index = 0; index < bk_num; index++) { - key_offset_bk[index] += sz_extend; - prot = prot_field_bk[index].prot; - field = prot_field_bk[index].key_field; - if (dpaa2_flow_l4_src_port_extract(prot, - field)) { - key_profile->l4_src_port_present = 1; - key_profile->l4_src_port_pos = end_pos + index; - key_profile->l4_src_port_offset = - key_offset_bk[index]; - } else if (dpaa2_flow_l4_dst_port_extract(prot, - field)) { - key_profile->l4_dst_port_present = 1; - key_profile->l4_dst_port_pos = end_pos + index; - key_profile->l4_dst_port_offset = - key_offset_bk[index]; - } - } - } + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, hd->protocol_id); + if (ret) + return ret; - pos = key_profile->raw_extract_pos; + ret = dpaa2_flow_identify_by_faf(flow, bit_offset, ecfg); + if (ret) + return ret; - for (index = 0; index < num_extracts; index++) { - if (index == num_extracts - 1) - item_size = last_extract_size; - else - item_size = DPAA2_FLOW_MAX_KEY_SIZE; - field = offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; - field |= item_size; + if (!spec) + return 0; - if (pos > 0) { - key_profile->key_offset[pos] = - key_profile->key_offset[pos - 1] + - key_profile->key_size[pos - 1]; - } else { - key_profile->key_offset[pos] = 0; - } - key_profile->key_size[pos] = item_size; - key_profile->prot_field[pos].type = DPAA2_NET_PROT_KEY; - key_profile->prot_field[pos].prot = NET_PROT_PAYLOAD; - key_profile->prot_field[pos].key_field = field; - - dpkg->extracts[pos].type = DPKG_EXTRACT_FROM_DATA; - dpkg->extracts[pos].extract.from_data.size = item_size; - dpkg->extracts[pos].extract.from_data.offset = offset; - offset += item_size; - pos++; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("vXLAN flow with spec is not supported without SP."); + return -ENOTSUP; } - if (bk_num) { - memcpy(&dpkg->extracts[pos], extract_bk, - bk_num * sizeof(struct dpkg_extract)); - memcpy(&key_profile->key_offset[end_pos], - key_offset_bk, bk_num * sizeof(uint8_t)); - memcpy(&key_profile->key_size[end_pos], - key_size_bk, bk_num * sizeof(uint8_t)); - memcpy(&key_profile->prot_field[end_pos], - prot_field_bk, bk_num * sizeof(struct key_prot_field)); - } + ret = dpaa2_flow_extract_support(_mask, hd->mask_support, hd->hdr_size); + if (ret) + return ret; - extract_extended = num_extracts - key_profile->raw_extract_num; - if (key_profile->ip_addr_type != IP_NONE_ADDR_EXTRACT) { - key_profile->ip_addr_extract_pos += extract_extended; - key_profile->ip_addr_extract_off += sz_extend; + if (mask->flags) { + if (spec->flags != VXLAN_HF_VNI) { + DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", + spec->flags, VXLAN_HF_VNI); + return -EINVAL; + } + if (mask->flags != 0xff) { + DPAA2_PMD_ERR("Not support to extract vxlan flag."); + return -EINVAL; + } } - key_profile->raw_extract_num = num_extracts; - key_profile->num += extract_extended; - key_profile->key_max_size += sz_extend; - dpkg->num_extracts += extract_extended; - if (!ret && recfg) - (*recfg) |= dist_type; + if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { + ret = dpaa2_flow_add_soft_psr_extract_rule(flow, + DPAA2_VXLAN_VNI_OFFSET, sizeof(mask->vni), + spec->vni, mask->vni, ecfg); + if (ret) + return ret; + } - return ret; + return 0; } -static inline int -dpaa2_flow_extract_search(struct dpaa2_key_profile *key_profile, - enum key_prot_type type, enum net_prot prot, uint32_t key_field) +static int +dpaa2_flow_ecpri_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) { - int pos; - struct key_prot_field *prot_field; - - if (dpaa2_flow_ip_address_extract(prot, key_field)) { - DPAA2_PMD_ERR("%s only for none IP address extract", - __func__); - return -EINVAL; - } + int ret; + uint32_t bit_offset; + const struct rte_flow_item_ecpri *spec, *mask; + const void *_mask; + struct rte_flow_item_ecpri local_mask; + struct dpaa2_dev_priv *priv = flow->priv; + int extract_nb, i; + uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; + uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; + uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; + uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; + union dpaa2_sp_fafe_parse fafe; - prot_field = key_profile->prot_field; - for (pos = 0; pos < key_profile->num; pos++) { - if (type == DPAA2_NET_PROT_KEY && - prot_field[pos].prot == prot && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - else if (type == DPAA2_FAF_KEY && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; - else if (type == DPAA2_PR_KEY && - prot_field[pos].key_field == key_field && - prot_field[pos].type == type) - return pos; + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("eCPRI flow is not supported without SP."); + return -ENOTSUP; } - if (type == DPAA2_NET_PROT_KEY && - dpaa2_flow_l4_src_port_extract(prot, key_field)) { - if (key_profile->l4_src_port_present) - return key_profile->l4_src_port_pos; - } else if (type == DPAA2_NET_PROT_KEY && - dpaa2_flow_l4_dst_port_extract(prot, key_field)) { - if (key_profile->l4_dst_port_present) - return key_profile->l4_dst_port_pos; + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + if (pattern->mask) { + memcpy(&local_mask, pattern->mask, sizeof(struct rte_flow_item_ecpri)); + local_mask.hdr.common.u32 = rte_be_to_cpu_32(local_mask.hdr.common.u32); + mask = &local_mask; + } else { + mask = hd->mask_support; } + _mask = mask; - return -ENXIO; -} - -static inline int -dpaa2_flow_extract_key_offset(struct dpaa2_key_profile *key_profile, - enum key_prot_type type, enum net_prot prot, uint32_t key_field) -{ - int i; - - i = dpaa2_flow_extract_search(key_profile, type, prot, key_field); - if (i >= 0) - return key_profile->key_offset[i]; - else - return i; -} - -static int -dpaa2_flow_faf_add_rule(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, - enum dpaa2_rx_faf_offset faf_bit_off, - int group, - enum dpaa2_flow_dist_type dist_type) -{ - int offset; - uint8_t *key_addr; - uint8_t *mask_addr; - struct dpaa2_key_extract *key_extract; - struct dpaa2_key_profile *key_profile; - uint8_t faf_byte = faf_bit_off / 8; - uint8_t faf_bit_in_byte = faf_bit_off % 8; + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, hd->protocol_id); + if (ret) + return ret; - faf_bit_in_byte = 7 - faf_bit_in_byte; + ret = dpaa2_flow_identify_by_faf(flow, bit_offset, ecfg); + if (ret) + return ret; - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - key_extract = &priv->extract.qos_key_extract; - key_profile = &key_extract->key_profile; + if (!spec) + return 0; - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (offset < 0) { - DPAA2_PMD_ERR("%s QoS key extract failed", __func__); - return -EINVAL; - } - key_addr = flow->qos_key_addr + offset; - mask_addr = flow->qos_mask_addr + offset; + ret = dpaa2_flow_extract_support(_mask, hd->mask_support, hd->hdr_size); + if (ret) + return ret; - if (!(*key_addr) && - key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT && - offset >= flow->qos_rule_size) - flow->qos_rule_size = offset + sizeof(uint8_t); + memset(&fafe, 0, sizeof(union dpaa2_sp_fafe_parse)); + extract_nb = dpaa2_parser_ecpri_extract(spec, mask, + rule_data, mask_data, extract_size, extract_off, + &fafe, DPAA2_ECPRI_MAX_EXTRACT_NB); + if (extract_nb < 0) { + DPAA2_PMD_ERR("Extract eCPRI from spec/mask failed(%d)", extract_nb); - *key_addr |= (1 << faf_bit_in_byte); - *mask_addr |= (1 << faf_bit_in_byte); + return extract_nb; } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - key_extract = &priv->extract.tc_key_extract[group]; - key_profile = &key_extract->key_profile; - - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (offset < 0) { - DPAA2_PMD_ERR("%s TC[%d] key extract failed", - __func__, group); - return -EINVAL; - } - key_addr = flow->fs_key_addr + offset; - mask_addr = flow->fs_mask_addr + offset; - - if (!(*key_addr) && - key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT && - offset >= flow->fs_rule_size) - flow->fs_rule_size = offset + sizeof(uint8_t); - - *key_addr |= (1 << faf_bit_in_byte); - *mask_addr |= (1 << faf_bit_in_byte); + for (i = 0; i < extract_nb; i++) { + ret = dpaa2_flow_add_soft_psr_extract_rule(flow, + extract_off[i], extract_size[i], + &rule_data[i], &mask_data[i], ecfg); + if (ret) + return ret; } return 0; } static inline int -dpaa2_flow_pr_rule_data_set(struct dpaa2_dev_flow *flow, - struct dpaa2_key_profile *key_profile, - uint32_t pr_offset, uint32_t pr_size, - const void *key, const void *mask, - enum dpaa2_flow_dist_type dist_type) +dpaa2_flow_raw_rule_data_set(struct dpaa2_generic_flow *flow, + uint32_t extract_offset, int size, const void *key, const void *mask) { - int offset; - uint32_t pr_field = pr_offset << 16 | pr_size; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + int extract_size = size > DPAA2_FLOW_MAX_KEY_SIZE ? + DPAA2_FLOW_MAX_KEY_SIZE : size; + int offset, field; char offset_info[64], size_info[64], rule_size_info[64]; + field = extract_offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; + field |= extract_size; offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_PR_KEY, NET_PROT_NONE, pr_field); + DPAA2_NET_PROT_KEY, NET_PROT_PAYLOAD, field); if (offset < 0) { - DPAA2_PMD_ERR("PR off(%d)/size(%d) does not exist!", - pr_offset, pr_size); + DPAA2_PMD_ERR("offset(%d)/size(%d) raw extract failed", + extract_offset, size); return -EINVAL; } - sprintf(offset_info, "offset(%d)", offset); - sprintf(size_info, "size(%d)", pr_size); - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, pr_size); - memcpy((flow->qos_mask_addr + offset), mask, pr_size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + pr_size; - } else if ((offset + pr_size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", - offset_info, rule_size_info, - offset_info, size_info, - rule_size_info); - return -EINVAL; - } - } - } - - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, pr_size); - memcpy((flow->fs_mask_addr + offset), mask, pr_size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + pr_size; - } else if ((offset + pr_size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s < %s, but %s + %s > %s", - offset_info, rule_size_info, - offset_info, size_info, - rule_size_info); - return -EINVAL; - } - } + snprintf(offset_info, 64, "offset(%d)", offset); + snprintf(size_info, 64, "size(%d)", size); + + snprintf(rule_size_info, 64, "%s rule size(%d)", + flow->type == DPAA2_FLOW_QOS_TYPE ? + "QoS" : "FS", flow->rule_size); + + memcpy((flow->key_addr + offset), key, size); + memcpy((flow->mask_addr + offset), mask, size); + if (offset >= flow->rule_size) { + flow->rule_size = offset + size; + } else if ((offset + size) > flow->rule_size) { + DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", + __func__, offset_info, rule_size_info, + offset_info, size_info, rule_size_info); + return -EINVAL; } return 0; } -static inline int -dpaa2_flow_hdr_rule_data_set(struct dpaa2_dev_flow *flow, - struct dpaa2_key_profile *key_profile, - enum net_prot prot, uint32_t field, int size, - const void *key, const void *mask, - enum dpaa2_flow_dist_type dist_type) +static int +dpaa2_flow_raw_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) { - int offset; - char offset_info[64], size_info[64], rule_size_info[64]; + int ret; + const struct rte_flow_item_raw *spec = pattern->spec; + const struct rte_flow_item_raw *mask = pattern->mask; - if (dpaa2_flow_ip_address_extract(prot, field)) { - DPAA2_PMD_ERR("%s only for none IP address extract", - __func__); - return -EINVAL; - } + RTE_SET_USED(hd); - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_NET_PROT_KEY, prot, field); - if (offset < 0) { - DPAA2_PMD_ERR("P(%d)/F(%d) does not exist!", - prot, field); + /* Need both spec and mask */ + if (!spec || !mask) { + DPAA2_PMD_ERR("spec or mask not present."); return -EINVAL; } - sprintf(offset_info, "offset(%d)", offset); - sprintf(size_info, "size(%d)", size); - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, size); - memcpy((flow->qos_mask_addr + offset), mask, size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + size; - } else if ((offset + size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } - } + if (spec->relative) { + /* TBD: relative offset support. + * To support relative offset of previous L3 protocol item, + * extracts should be expanded to identify if the frame is: + * vlan or none-vlan. + * + * To support relative offset of previous L4 protocol item, + * extracts should be expanded to identify if the frame is: + * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6. + */ + DPAA2_PMD_ERR("relative not supported."); + return -EINVAL; } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, size); - memcpy((flow->fs_mask_addr + offset), mask, size); - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + size; - } else if ((offset + size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } - } + if (spec->search) { + DPAA2_PMD_ERR("search not supported."); + return -EINVAL; } - return 0; -} - -static inline int -dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow, - struct dpaa2_key_profile *key_profile, - uint32_t extract_offset, int size, - const void *key, const void *mask, - enum dpaa2_flow_dist_type dist_type) -{ - int extract_size = size > DPAA2_FLOW_MAX_KEY_SIZE ? - DPAA2_FLOW_MAX_KEY_SIZE : size; - int offset, field; - char offset_info[64], size_info[64], rule_size_info[64]; - - field = extract_offset << DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT; - field |= extract_size; - offset = dpaa2_flow_extract_key_offset(key_profile, - DPAA2_NET_PROT_KEY, NET_PROT_PAYLOAD, field); - if (offset < 0) { - DPAA2_PMD_ERR("offset(%d)/size(%d) raw extract failed", - extract_offset, size); + /* Spec len and mask len should be same */ + if (spec->length != mask->length) { + DPAA2_PMD_ERR("Spec len and mask len mismatch."); return -EINVAL; } - sprintf(offset_info, "offset(%d)", offset); - sprintf(size_info, "size(%d)", size); - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - sprintf(rule_size_info, "qos rule size(%d)", - flow->qos_rule_size); - memcpy((flow->qos_key_addr + offset), key, size); - memcpy((flow->qos_mask_addr + offset), mask, size); - if (offset >= flow->qos_rule_size) { - flow->qos_rule_size = offset + size; - } else if ((offset + size) > flow->qos_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; - } + ret = dpaa2_flow_extract_add_raw(flow, spec->offset, spec->length, ecfg); + if (ret) { + DPAA2_PMD_ERR("QoS Extract RAW add failed(%d).", ret); + return ret; } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - sprintf(rule_size_info, "fs rule size(%d)", - flow->fs_rule_size); - memcpy((flow->fs_key_addr + offset), key, size); - memcpy((flow->fs_mask_addr + offset), mask, size); - if (offset >= flow->fs_rule_size) { - flow->fs_rule_size = offset + size; - } else if ((offset + size) > flow->fs_rule_size) { - DPAA2_PMD_ERR("%s: %s < %s, but %s + %s > %s", - __func__, offset_info, rule_size_info, - offset_info, size_info, rule_size_info); - return -EINVAL; + if (flow->type == DPAA2_FLOW_QOS_TYPE || flow->type == DPAA2_FLOW_FS_TYPE) { + ret = dpaa2_flow_raw_rule_data_set(flow, spec->offset, spec->length, + spec->pattern, mask->pattern); + if (ret) { + DPAA2_PMD_ERR("QoS RAW rule data set failed(%d)", ret); + return ret; } } @@ -1634,3774 +1374,3158 @@ dpaa2_flow_raw_rule_data_set(struct dpaa2_dev_flow *flow, } static int -dpaa2_flow_extract_support(const uint8_t *mask_src, - enum rte_flow_item_type type) +dpaa2_flow_geneve_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) { - char mask[64]; - int i, size = 0; - const char *mask_support = 0; - - switch (type) { - case RTE_FLOW_ITEM_TYPE_ETH: - mask_support = (const char *)&dpaa2_flow_item_eth_mask; - size = sizeof(struct rte_flow_item_eth); - break; - case RTE_FLOW_ITEM_TYPE_VLAN: - mask_support = (const char *)&dpaa2_flow_item_vlan_mask; - size = sizeof(struct rte_flow_item_vlan); - break; - case RTE_FLOW_ITEM_TYPE_IPV4: - mask_support = (const char *)&dpaa2_flow_item_ipv4_mask; - size = sizeof(struct rte_flow_item_ipv4); - break; - case RTE_FLOW_ITEM_TYPE_IPV6: - mask_support = (const char *)&dpaa2_flow_item_ipv6_mask; - size = sizeof(struct rte_flow_item_ipv6); - break; - case RTE_FLOW_ITEM_TYPE_ICMP: - mask_support = (const char *)&dpaa2_flow_item_icmp_mask; - size = sizeof(struct rte_flow_item_icmp); - break; - case RTE_FLOW_ITEM_TYPE_UDP: - mask_support = (const char *)&dpaa2_flow_item_udp_mask; - size = sizeof(struct rte_flow_item_udp); - break; - case RTE_FLOW_ITEM_TYPE_TCP: - mask_support = (const char *)&dpaa2_flow_item_tcp_mask; - size = sizeof(struct rte_flow_item_tcp); - break; - case RTE_FLOW_ITEM_TYPE_ESP: - mask_support = (const char *)&dpaa2_flow_item_esp_mask; - size = sizeof(struct rte_flow_item_esp); - break; - case RTE_FLOW_ITEM_TYPE_AH: - mask_support = (const char *)&dpaa2_flow_item_ah_mask; - size = sizeof(struct rte_flow_item_ah); - break; - case RTE_FLOW_ITEM_TYPE_SCTP: - mask_support = (const char *)&dpaa2_flow_item_sctp_mask; - size = sizeof(struct rte_flow_item_sctp); - break; - case RTE_FLOW_ITEM_TYPE_GRE: - mask_support = (const char *)&dpaa2_flow_item_gre_mask; - size = sizeof(struct rte_flow_item_gre); - break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); - break; - case RTE_FLOW_ITEM_TYPE_GTP: - mask_support = (const char *)&dpaa2_flow_item_gtp_mask; - size = sizeof(struct rte_flow_item_gtp); - break; - case RTE_FLOW_ITEM_TYPE_MPLS: - mask_support = (const char *)&dpaa2_flow_item_mpls_mask; - size = sizeof(struct rte_flow_item_mpls); - break; - case RTE_FLOW_ITEM_TYPE_PPPOES: - mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; - size = sizeof(struct rte_flow_item_pppoe); - break; - default: - return -EINVAL; - } - - memcpy(mask, mask_support, size); - - for (i = 0; i < size; i++) - mask[i] = (mask[i] | mask_src[i]); + int ret; + const struct rte_flow_item_geneve *spec = NULL, *mask = NULL; + struct dpaa2_dev_priv *priv = flow->priv; - if (memcmp(mask, mask_support, size)) + if (!priv->sp_protocol) { + DPAA2_PMD_ERR("GENEVE flow is not supported without SP."); return -ENOTSUP; + } - return 0; -} - -static int -dpaa2_flow_identify_by_faf(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, - enum dpaa2_rx_faf_offset faf_off, - enum dpaa2_flow_dist_type dist_type, - int group, int *recfg) -{ - int ret, index, local_cfg = 0; - struct dpaa2_key_extract *extract; - struct dpaa2_key_profile *key_profile; - uint8_t faf_byte = faf_off / 8; - - if (dist_type & DPAA2_FLOW_QOS_TYPE) { - extract = &priv->extract.qos_key_extract; - key_profile = &extract->key_profile; - - index = dpaa2_flow_extract_search(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (index < 0) { - ret = dpaa2_flow_faf_add_hdr(faf_byte, - priv, DPAA2_FLOW_QOS_TYPE, group, - NULL); - if (ret) { - DPAA2_PMD_ERR("QOS faf extract add failed"); + spec = pattern->spec; + mask = pattern->mask ? pattern->mask : hd->mask_support; - return -EINVAL; - } - local_cfg |= DPAA2_FLOW_QOS_TYPE; - } + if (!spec || !mask) + return 0; - ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group, - DPAA2_FLOW_QOS_TYPE); - if (ret) { - DPAA2_PMD_ERR("QoS faf rule set failed"); - return -EINVAL; - } + if (mask->protocol && mask->protocol != 0xffff) { + DPAA2_PMD_ERR("Not support to extract geneve protocol."); + return -EINVAL; } - if (dist_type & DPAA2_FLOW_FS_TYPE) { - extract = &priv->extract.tc_key_extract[group]; - key_profile = &extract->key_profile; - - index = dpaa2_flow_extract_search(key_profile, - DPAA2_FAF_KEY, NET_PROT_NONE, faf_byte); - if (index < 0) { - ret = dpaa2_flow_faf_add_hdr(faf_byte, - priv, DPAA2_FLOW_FS_TYPE, group, - NULL); - if (ret) { - DPAA2_PMD_ERR("FS[%d] faf extract add failed", - group); - - return -EINVAL; - } - local_cfg |= DPAA2_FLOW_FS_TYPE; - } - - ret = dpaa2_flow_faf_add_rule(priv, flow, faf_off, group, - DPAA2_FLOW_FS_TYPE); - if (ret) { - DPAA2_PMD_ERR("FS[%d] faf rule set failed", - group); - return -EINVAL; - } + if (mask->protocol) { + ret = dpaa2_flow_add_soft_psr_extract_rule(flow, + DPAA2_GENEVE_PROTOCOL_OFFSET, + sizeof(mask->protocol), &spec->protocol, + &mask->protocol, ecfg); + if (ret) + return ret; } - if (recfg) - *recfg |= local_cfg; + if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { + ret = dpaa2_flow_add_soft_psr_extract_rule(flow, + DPAA2_GENEVE_VNI_OFFSET, sizeof(mask->vni), + spec->vni, mask->vni, ecfg); + if (ret) + return ret; + } return 0; } static int -dpaa2_flow_add_pr_extract_rule(struct dpaa2_dev_flow *flow, - uint32_t pr_offset, uint32_t pr_size, - const void *key, const void *mask, - struct dpaa2_dev_priv *priv, int tc_id, int *recfg, - enum dpaa2_flow_dist_type dist_type) +dpaa2_flow_general_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item *pattern, + const struct dpaa2_flow_proto_handle *hd, int *ecfg) { - int index, ret, local_cfg = 0; - struct dpaa2_key_extract *key_extract; - struct dpaa2_key_profile *key_profile; - uint32_t pr_field = pr_offset << 16 | pr_size; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; - else - key_extract = &priv->extract.tc_key_extract[tc_id]; + int ret, i; + uint32_t bit_offset; + const uint8_t *spec_u8 = pattern->spec, *mask_u8 = pattern->mask; + const char zero_cmp[128] = {0}; - key_profile = &key_extract->key_profile; - - index = dpaa2_flow_extract_search(key_profile, - DPAA2_PR_KEY, NET_PROT_NONE, pr_field); - if (index < 0) { - ret = dpaa2_flow_pr_add_hdr(pr_offset, - pr_size, priv, - dist_type, tc_id, NULL); - if (ret) { - DPAA2_PMD_ERR("PR add off(%d)/size(%d) failed", - pr_offset, pr_size); + if (hd->force_psr || !spec_u8) { + ret = dpaa2_protocol_psr_bit_offset(&bit_offset, hd->protocol_id); + if (ret) + return ret; + ret = dpaa2_flow_identify_by_faf(flow, bit_offset, ecfg); + if (ret) return ret; - } - local_cfg |= dist_type; } - ret = dpaa2_flow_pr_rule_data_set(flow, key_profile, - pr_offset, pr_size, key, mask, dist_type); - if (ret) { - DPAA2_PMD_ERR("PR off(%d)/size(%d) rule data set failed", - pr_offset, pr_size); + if (!spec_u8) + return 0; + + if (!mask_u8) + mask_u8 = hd->mask_support; + ret = dpaa2_flow_extract_support(mask_u8, hd->mask_support, hd->hdr_size); + if (ret) return ret; - } - if (recfg) - *recfg |= local_cfg; + for (i = 0; i < hd->fields_num; i++) { + if (!memcmp(mask_u8 + hd->field_offset[i], zero_cmp, hd->field_size[i])) + continue; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, hd->prot, + hd->fields[i], spec_u8 + hd->field_offset[i], + mask_u8 + hd->field_offset[i], hd->field_size[i], ecfg); + if (ret) + return ret; + } return 0; } -static int -dpaa2_flow_add_hdr_extract_rule(struct dpaa2_dev_flow *flow, - enum net_prot prot, uint32_t field, - const void *key, const void *mask, int size, - struct dpaa2_dev_priv *priv, int tc_id, int *recfg, - enum dpaa2_flow_dist_type dist_type) -{ - int index, ret, local_cfg = 0; - struct dpaa2_key_extract *key_extract; - struct dpaa2_key_profile *key_profile; - - if (dpaa2_flow_ip_address_extract(prot, field)) - return -EINVAL; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) - key_extract = &priv->extract.qos_key_extract; - else - key_extract = &priv->extract.tc_key_extract[tc_id]; - - key_profile = &key_extract->key_profile; - - index = dpaa2_flow_extract_search(key_profile, - DPAA2_NET_PROT_KEY, prot, field); - if (index < 0) { - ret = dpaa2_flow_extract_add_hdr(prot, - field, size, priv, - dist_type, tc_id, NULL); - if (ret) { - DPAA2_PMD_ERR("QoS Extract P(%d)/F(%d) failed", - prot, field); - - return ret; +/** Make sure DPAA2_RTE_FLOW_ITEM_MAX > max of enum rte_flow_item_type.*/ +#define DPAA2_RTE_FLOW_ITEM_MAX 64 +static const struct dpaa2_flow_proto_handle s_dpaa2_flow_proto_handle[DPAA2_RTE_FLOW_ITEM_MAX] = { + [RTE_FLOW_ITEM_TYPE_ETH] = { + "eth", + dpaa2_flow_general_extract_rule_set, + dpaa2_flow_tunnel_eth_extract_rule_set, + DPAA2_PARSER_MAC_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_ETH, + &dpaa2_flow_item_eth_mask, sizeof(struct rte_flow_item_eth), + false, NET_PROT_ETH, 3, + .fields = { + NH_FLD_ETH_SA, NH_FLD_ETH_DA, NH_FLD_ETH_TYPE + }, + .field_offset = { + offsetof(struct rte_flow_item_eth, src), + offsetof(struct rte_flow_item_eth, dst), + offsetof(struct rte_flow_item_eth, type) + }, + .field_size = { + RTE_ETHER_ADDR_LEN, RTE_ETHER_ADDR_LEN, sizeof(rte_be16_t) } - local_cfg |= dist_type; - } - - ret = dpaa2_flow_hdr_rule_data_set(flow, key_profile, - prot, field, size, key, mask, dist_type); - if (ret) { - DPAA2_PMD_ERR("QoS P(%d)/F(%d) rule data set failed", - prot, field); - - return ret; - } - - if (recfg) - *recfg |= local_cfg; - - return 0; -} - -static int -dpaa2_flow_add_ipaddr_extract_rule(struct dpaa2_dev_flow *flow, - enum net_prot prot, uint32_t field, - const void *key, const void *mask, int size, - struct dpaa2_dev_priv *priv, int tc_id, int *recfg, - enum dpaa2_flow_dist_type dist_type) -{ - int local_cfg = 0, num, ipaddr_extract_len = 0; - struct dpaa2_key_extract *key_extract; - struct dpaa2_key_profile *key_profile; - struct dpkg_profile_cfg *dpkg; - uint8_t *key_addr, *mask_addr; - union ip_addr_extract_rule *ip_addr_data; - union ip_addr_extract_rule *ip_addr_mask; - enum net_prot orig_prot; - uint32_t orig_field; - - if (prot != NET_PROT_IPV4 && prot != NET_PROT_IPV6) - return -EINVAL; - - if (prot == NET_PROT_IPV4 && field != NH_FLD_IPV4_SRC_IP && - field != NH_FLD_IPV4_DST_IP) { - return -EINVAL; - } - - if (prot == NET_PROT_IPV6 && field != NH_FLD_IPV6_SRC_IP && - field != NH_FLD_IPV6_DST_IP) { - return -EINVAL; - } - - orig_prot = prot; - orig_field = field; - - if (prot == NET_PROT_IPV4 && - field == NH_FLD_IPV4_SRC_IP) { - prot = NET_PROT_IP; - field = NH_FLD_IP_SRC; - } else if (prot == NET_PROT_IPV4 && - field == NH_FLD_IPV4_DST_IP) { - prot = NET_PROT_IP; - field = NH_FLD_IP_DST; - } else if (prot == NET_PROT_IPV6 && - field == NH_FLD_IPV6_SRC_IP) { - prot = NET_PROT_IP; - field = NH_FLD_IP_SRC; - } else if (prot == NET_PROT_IPV6 && - field == NH_FLD_IPV6_DST_IP) { - prot = NET_PROT_IP; - field = NH_FLD_IP_DST; - } else { - DPAA2_PMD_ERR("Inval P(%d)/F(%d) to extract ip address", - prot, field); - return -EINVAL; - } - - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - key_extract = &priv->extract.qos_key_extract; - key_profile = &key_extract->key_profile; - dpkg = &key_extract->dpkg; - num = key_profile->num; - key_addr = flow->qos_key_addr; - mask_addr = flow->qos_mask_addr; - } else { - key_extract = &priv->extract.tc_key_extract[tc_id]; - key_profile = &key_extract->key_profile; - dpkg = &key_extract->dpkg; - num = key_profile->num; - key_addr = flow->fs_key_addr; - mask_addr = flow->fs_mask_addr; - } - - if (num >= DPKG_MAX_NUM_OF_EXTRACTS) { - DPAA2_PMD_ERR("Number of extracts overflows"); - return -EINVAL; - } - - if (key_profile->ip_addr_type == IP_NONE_ADDR_EXTRACT) { - if (field == NH_FLD_IP_SRC) - key_profile->ip_addr_type = IP_SRC_EXTRACT; - else - key_profile->ip_addr_type = IP_DST_EXTRACT; - ipaddr_extract_len = size; - - key_profile->ip_addr_extract_pos = num; - if (num > 0) { - key_profile->ip_addr_extract_off = - key_profile->key_offset[num - 1] + - key_profile->key_size[num - 1]; - } else { - key_profile->ip_addr_extract_off = 0; + }, + [RTE_FLOW_ITEM_TYPE_VLAN] = { + "vlan", + dpaa2_flow_general_extract_rule_set, + dpaa2_flow_tunnel_vlan_extract_rule_set, + DPAA2_PARSER_VLAN_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_VLAN, + &dpaa2_flow_item_vlan_mask, sizeof(struct rte_flow_item_vlan), + false, NET_PROT_VLAN, 1, + .fields = { + NH_FLD_VLAN_TCI + }, + .field_offset = { + offsetof(struct rte_flow_item_vlan, tci) + }, + .field_size = { + sizeof(rte_be16_t) } - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; - } else if (key_profile->ip_addr_type == IP_SRC_EXTRACT) { - if (field == NH_FLD_IP_SRC) { - ipaddr_extract_len = size; - goto rule_configure; + }, + [RTE_FLOW_ITEM_TYPE_ICMP] = { + "icmp", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_ICMP_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_ICMP, + &dpaa2_flow_item_icmp_mask, sizeof(struct rte_flow_item_icmp), + false, NET_PROT_ICMP, 2, + .fields = { + NH_FLD_ICMP_TYPE, NH_FLD_ICMP_CODE + }, + .field_offset = { + offsetof(struct rte_flow_item_icmp, hdr.icmp_type), + offsetof(struct rte_flow_item_icmp, hdr.icmp_code) + }, + .field_size = { + sizeof(uint8_t), sizeof(uint8_t) } - key_profile->ip_addr_type = IP_SRC_DST_EXTRACT; - ipaddr_extract_len = size * 2; - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; - } else if (key_profile->ip_addr_type == IP_DST_EXTRACT) { - if (field == NH_FLD_IP_DST) { - ipaddr_extract_len = size; - goto rule_configure; + }, + [RTE_FLOW_ITEM_TYPE_UDP] = { + "udp", + dpaa2_flow_general_extract_rule_set, + dpaa2_flow_general_tunnel_extract_rule_set, + DPAA2_PARSER_UDP_ID, DPAA2_PARSER_TUNNEL_UDP_ID, RTE_FLOW_ITEM_TYPE_UDP, + &dpaa2_flow_item_udp_mask, sizeof(struct rte_flow_item_udp), + true, NET_PROT_UDP, 2, + .fields = { + NH_FLD_UDP_PORT_SRC, NH_FLD_UDP_PORT_DST + }, + .field_offset = { + offsetof(struct rte_flow_item_udp, hdr.src_port), + offsetof(struct rte_flow_item_udp, hdr.dst_port) + }, + .field_size = { + sizeof(rte_be16_t), sizeof(rte_be16_t) } - key_profile->ip_addr_type = IP_DST_SRC_EXTRACT; - ipaddr_extract_len = size * 2; - key_profile->key_max_size += NH_FLD_IPV6_ADDR_SIZE; - } - key_profile->num++; - key_profile->prot_field[num].type = DPAA2_NET_PROT_KEY; - - dpkg->extracts[num].extract.from_hdr.prot = prot; - dpkg->extracts[num].extract.from_hdr.field = field; - dpkg->extracts[num].extract.from_hdr.type = DPKG_FULL_FIELD; - dpkg->num_extracts++; - - if (dist_type == DPAA2_FLOW_QOS_TYPE) - local_cfg = DPAA2_FLOW_QOS_TYPE; - else - local_cfg = DPAA2_FLOW_FS_TYPE; - -rule_configure: - key_addr += key_profile->ip_addr_extract_off; - ip_addr_data = (union ip_addr_extract_rule *)key_addr; - mask_addr += key_profile->ip_addr_extract_off; - ip_addr_mask = (union ip_addr_extract_rule *)mask_addr; - - if (orig_prot == NET_PROT_IPV4 && - orig_field == NH_FLD_IPV4_SRC_IP) { - if (key_profile->ip_addr_type == IP_SRC_EXTRACT || - key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) { - memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_src, - key, size); - memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_src, - mask, size); - } else { - memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_src, - key, size); - memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_src, - mask, size); + }, + [RTE_FLOW_ITEM_TYPE_TCP] = { + "tcp", + dpaa2_flow_general_extract_rule_set, + dpaa2_flow_general_tunnel_extract_rule_set, + DPAA2_PARSER_TCP_ID, DPAA2_PARSER_TUNNEL_TCP_ID, RTE_FLOW_ITEM_TYPE_TCP, + &dpaa2_flow_item_tcp_mask, sizeof(struct rte_flow_item_tcp), + true, NET_PROT_TCP, 2, + .fields = { + NH_FLD_TCP_PORT_SRC, NH_FLD_TCP_PORT_DST + }, + .field_offset = { + offsetof(struct rte_flow_item_tcp, hdr.src_port), + offsetof(struct rte_flow_item_tcp, hdr.dst_port) + }, + .field_size = { + sizeof(rte_be16_t), sizeof(rte_be16_t) } - } else if (orig_prot == NET_PROT_IPV4 && - orig_field == NH_FLD_IPV4_DST_IP) { - if (key_profile->ip_addr_type == IP_DST_EXTRACT || - key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) { - memcpy(&ip_addr_data->ipv4_ds_addr.ipv4_dst, - key, size); - memcpy(&ip_addr_mask->ipv4_ds_addr.ipv4_dst, - mask, size); - } else { - memcpy(&ip_addr_data->ipv4_sd_addr.ipv4_dst, - key, size); - memcpy(&ip_addr_mask->ipv4_sd_addr.ipv4_dst, - mask, size); + }, + [RTE_FLOW_ITEM_TYPE_ESP] = { + "esp", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_IPSEC_ESP_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_ESP, + &dpaa2_flow_item_esp_mask, sizeof(struct rte_flow_item_esp), + true, NET_PROT_IPSEC_ESP, 2, + .fields = { + NH_FLD_IPSEC_ESP_SPI, NH_FLD_IPSEC_ESP_SEQUENCE_NUM + }, + .field_offset = { + offsetof(struct rte_flow_item_esp, hdr.spi), + offsetof(struct rte_flow_item_esp, hdr.seq) + }, + .field_size = { + sizeof(rte_be32_t), sizeof(rte_be32_t) } - } else if (orig_prot == NET_PROT_IPV6 && - orig_field == NH_FLD_IPV6_SRC_IP) { - if (key_profile->ip_addr_type == IP_SRC_EXTRACT || - key_profile->ip_addr_type == IP_SRC_DST_EXTRACT) { - memcpy(ip_addr_data->ipv6_sd_addr.ipv6_src, - key, size); - memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_src, - mask, size); - } else { - memcpy(ip_addr_data->ipv6_ds_addr.ipv6_src, - key, size); - memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_src, - mask, size); + }, + [RTE_FLOW_ITEM_TYPE_AH] = { + "ah", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_IPSEC_AH_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_AH, + &dpaa2_flow_item_ah_mask, sizeof(struct rte_flow_item_ah), + true, NET_PROT_IPSEC_AH, 1, + .fields = { + NH_FLD_IPSEC_AH_SPI + }, + .field_offset = { + offsetof(struct rte_flow_item_ah, spi) + }, + .field_size = { + sizeof(rte_be32_t) } - } else if (orig_prot == NET_PROT_IPV6 && - orig_field == NH_FLD_IPV6_DST_IP) { - if (key_profile->ip_addr_type == IP_DST_EXTRACT || - key_profile->ip_addr_type == IP_DST_SRC_EXTRACT) { - memcpy(ip_addr_data->ipv6_ds_addr.ipv6_dst, - key, size); - memcpy(ip_addr_mask->ipv6_ds_addr.ipv6_dst, - mask, size); - } else { - memcpy(ip_addr_data->ipv6_sd_addr.ipv6_dst, - key, size); - memcpy(ip_addr_mask->ipv6_sd_addr.ipv6_dst, - mask, size); + }, + [RTE_FLOW_ITEM_TYPE_SCTP] = { + "sctp", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_SCTP_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_SCTP, + &dpaa2_flow_item_sctp_mask, sizeof(struct rte_flow_item_sctp), + true, NET_PROT_SCTP, 2, + .fields = { + NH_FLD_SCTP_PORT_SRC, NH_FLD_SCTP_PORT_DST + }, + .field_offset = { + offsetof(struct rte_flow_item_sctp, hdr.src_port), + offsetof(struct rte_flow_item_sctp, hdr.dst_port), + }, + .field_size = { + sizeof(rte_be16_t), sizeof(rte_be16_t) } - } - - if (dist_type == DPAA2_FLOW_QOS_TYPE) { - flow->qos_rule_size = - key_profile->ip_addr_extract_off + ipaddr_extract_len; - } else { - flow->fs_rule_size = - key_profile->ip_addr_extract_off + ipaddr_extract_len; - } - - if (recfg) - *recfg |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_tunnel_eth(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_eth *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_eth_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (!spec) - return 0; - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ETH); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ethernet failed"); - - return ret; - } - - if (memcmp((const char *)&mask->src, - zero_cmp, RTE_ETHER_ADDR_LEN)) { - /*SRC[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR0_OFFSET, - 1, &spec->src.addr_bytes[0], - &mask->src.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[1:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR1_OFFSET, - 2, &spec->src.addr_bytes[1], - &mask->src.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[3:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR3_OFFSET, - 1, &spec->src.addr_bytes[3], - &mask->src.addr_bytes[3], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*SRC[4:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR4_OFFSET, - 2, &spec->src.addr_bytes[4], - &mask->src.addr_bytes[4], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - /*SRC[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR0_OFFSET, - 1, &spec->src.addr_bytes[0], - &mask->src.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - /*SRC[1:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR1_OFFSET, - 2, &spec->src.addr_bytes[1], - &mask->src.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - /*SRC[3:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR3_OFFSET, - 1, &spec->src.addr_bytes[3], - &mask->src.addr_bytes[3], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - /*SRC[4:2]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_SADDR4_OFFSET, - 2, &spec->src.addr_bytes[4], - &mask->src.addr_bytes[4], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - if (memcmp((const char *)&mask->dst, - zero_cmp, RTE_ETHER_ADDR_LEN)) { - /*DST[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR0_OFFSET, - 1, &spec->dst.addr_bytes[0], - &mask->dst.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[1:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR1_OFFSET, - 1, &spec->dst.addr_bytes[1], - &mask->dst.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[2:3]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR2_OFFSET, - 3, &spec->dst.addr_bytes[2], - &mask->dst.addr_bytes[2], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - /*DST[5:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR5_OFFSET, - 1, &spec->dst.addr_bytes[5], - &mask->dst.addr_bytes[5], - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - /*DST[0:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR0_OFFSET, - 1, &spec->dst.addr_bytes[0], - &mask->dst.addr_bytes[0], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - /*DST[1:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR1_OFFSET, - 1, &spec->dst.addr_bytes[1], - &mask->dst.addr_bytes[1], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - /*DST[2:3]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR2_OFFSET, - 3, &spec->dst.addr_bytes[2], - &mask->dst.addr_bytes[2], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - /*DST[5:1]*/ - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_DADDR5_OFFSET, - 1, &spec->dst.addr_bytes[5], - &mask->dst.addr_bytes[5], - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - if (memcmp((const char *)&mask->type, - zero_cmp, sizeof(rte_be16_t))) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TYPE_OFFSET, - sizeof(rte_be16_t), &spec->type, &mask->type, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TYPE_OFFSET, - sizeof(rte_be16_t), &spec->type, &mask->type, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_eth(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_eth *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0}; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - if (dpaa2_pattern->in_tunnel) { - return dpaa2_configure_flow_tunnel_eth(flow, - dev, attr, pattern, device_configured); - } - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_eth_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ETH_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ETH_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ETH); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ethernet failed"); - - return ret; - } - - if (memcmp((const char *)&mask->src, - zero_cmp, RTE_ETHER_ADDR_LEN)) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_SA, &spec->src.addr_bytes, - &mask->src.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_SA, &spec->src.addr_bytes, - &mask->src.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - if (memcmp((const char *)&mask->dst, - zero_cmp, RTE_ETHER_ADDR_LEN)) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_DA, &spec->dst.addr_bytes, - &mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_DA, &spec->dst.addr_bytes, - &mask->dst.addr_bytes, RTE_ETHER_ADDR_LEN, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - if (memcmp((const char *)&mask->type, - zero_cmp, sizeof(rte_be16_t))) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_TYPE, &spec->type, - &mask->type, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ETH, - NH_FLD_ETH_TYPE, &spec->type, - &mask->type, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_tunnel_vlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_VLAN_FRAM, - DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_VLAN_FRAM, - DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of vlan not support."); - - return ret; - } - - if (!mask->tci) - return 0; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TCI_OFFSET, - sizeof(rte_be16_t), &spec->tci, &mask->tci, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_IN_TCI_OFFSET, - sizeof(rte_be16_t), &spec->tci, &mask->tci, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_vlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - if (dpaa2_pattern->in_tunnel) { - return dpaa2_configure_flow_tunnel_vlan(flow, - dev, attr, pattern, device_configured); - } - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_VLAN_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of vlan not support."); - return ret; - } - - if (!mask->tci) - return 0; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN, - NH_FLD_VLAN_TCI, &spec->tci, - &mask->tci, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_VLAN, - NH_FLD_VLAN_TCI, &spec->tci, - &mask->tci, sizeof(rte_be16_t), - priv, group, &local_cfg, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; -} - -static int -dpaa2_configure_flow_ipv4(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ipv4 *spec_ipv4 = 0, *mask_ipv4 = 0; - const void *key, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - int size; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec_ipv4 = pattern->spec; - mask_ipv4 = pattern->mask ? - pattern->mask : &dpaa2_flow_item_ipv4_mask; - - if (dpaa2_pattern->in_tunnel) { - if (spec_ipv4) { - DPAA2_PMD_ERR("Tunnel-IPv4 distribution not support"); - return -ENOTSUP; + }, + [RTE_FLOW_ITEM_TYPE_GRE] = { + "gre", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_GRE_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_GRE, + &dpaa2_flow_item_gre_mask, sizeof(struct rte_flow_item_gre), + false, NET_PROT_GRE, 1, + .fields = { + NH_FLD_GRE_TYPE + }, + .field_offset = { + offsetof(struct rte_flow_item_gre, protocol) + }, + .field_size = { + sizeof(rte_be16_t) } - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV4_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV4_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV4_FRAM, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); - if (ret) - return ret; - - if (!spec_ipv4) { - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv4, - RTE_FLOW_ITEM_TYPE_IPV4); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of IPv4 not support."); - return ret; - } - - if (mask_ipv4->hdr.src_addr) { - key = &spec_ipv4->hdr.src_addr; - mask = &mask_ipv4->hdr.src_addr; - size = sizeof(rte_be32_t); - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - if (mask_ipv4->hdr.dst_addr) { - key = &spec_ipv4->hdr.dst_addr; - mask = &mask_ipv4->hdr.dst_addr; - size = sizeof(rte_be32_t); - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV4, - NH_FLD_IPV4_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - if (mask_ipv4->hdr.next_proto_id) { - key = &spec_ipv4->hdr.next_proto_id; - mask = &mask_ipv4->hdr.next_proto_id; - size = sizeof(uint8_t); - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - return 0; -} - -static int -dpaa2_configure_flow_ipv6(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ipv6 *spec_ipv6 = 0, *mask_ipv6 = 0; - const void *key, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0}; - int size; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec_ipv6 = pattern->spec; - mask_ipv6 = pattern->mask ? pattern->mask : &dpaa2_flow_item_ipv6_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - if (spec_ipv6) { - DPAA2_PMD_ERR("Tunnel-IPv6 distribution not support"); - return -ENOTSUP; + }, + [RTE_FLOW_ITEM_TYPE_GTP] = { + "gtp", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_GTP_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_GTP, + &dpaa2_flow_item_gtp_mask, sizeof(struct rte_flow_item_gtp), + false, NET_PROT_GTP, 1, + .fields = { + NH_FLD_GTP_TEID + }, + .field_offset = { + offsetof(struct rte_flow_item_gtp, teid) + }, + .field_size = { + sizeof(rte_be32_t) } - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV6_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_IPV6_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; - } - - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, FAF_IPV6_FRAM, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); - if (ret) - return ret; - - if (!spec_ipv6) { - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask_ipv6, - RTE_FLOW_ITEM_TYPE_IPV6); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of IPv6 not support."); - return ret; - } - - if (memcmp((const char *)&mask_ipv6->hdr.src_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { - key = &spec_ipv6->hdr.src_addr; - mask = &mask_ipv6->hdr.src_addr; - size = NH_FLD_IPV6_ADDR_SIZE; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_SRC_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + }, + [RTE_FLOW_ITEM_TYPE_MPLS] = { + "mpls", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_MPLS_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_MPLS, + &dpaa2_flow_item_mpls_mask, sizeof(struct rte_flow_item_mpls), + false, NET_PROT_MPLS, 1, + .fields = { + NH_FLD_MPLS_MPLSL_1 + }, + .field_offset = { + offsetof(struct rte_flow_item_mpls, label_tc_s[0]) + }, + .field_size = { + sizeof(uint8_t) * 3 + } + }, + [RTE_FLOW_ITEM_TYPE_PPPOES] = { + "pppoes", + dpaa2_flow_general_extract_rule_set, + NULL, + DPAA2_PARSER_MPLS_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_PPPOES, + &dpaa2_flow_item_pppoe_mask, sizeof(struct rte_flow_item_pppoe), + false, NET_PROT_PPPOE, 1, + .fields = { + NH_FLD_PPPOE_CODE, NH_FLD_PPPOE_SID + }, + .field_offset = { + offsetof(struct rte_flow_item_pppoe, code), + offsetof(struct rte_flow_item_pppoe, session_id) + }, + .field_size = { + sizeof(uint8_t), sizeof(rte_be16_t) + } + }, + [RTE_FLOW_ITEM_TYPE_IPV4] = { + "ipv4", + dpaa2_flow_ip_extract_rule_set, + dpaa2_flow_general_tunnel_extract_rule_set, + DPAA2_PARSER_IPV4_ID, DPAA2_PARSER_TUNNEL_IPV4_ID, RTE_FLOW_ITEM_TYPE_IPV4, + &dpaa2_flow_item_ipv4_mask, sizeof(struct rte_flow_item_ipv4), + true, NET_PROT_IP, 4, + .fields = { + NH_FLD_IP_SRC, NH_FLD_IP_DST, NH_FLD_IP_PROTO, NH_OPT_IP_FRAG + }, + .field_offset = { + offsetof(struct rte_flow_item_ipv4, hdr.src_addr), + offsetof(struct rte_flow_item_ipv4, hdr.dst_addr), + offsetof(struct rte_flow_item_ipv4, hdr.next_proto_id), + offsetof(struct rte_flow_item_ipv4, hdr.fragment_offset), + }, + .field_size = { + sizeof(rte_be32_t), sizeof(rte_be32_t), sizeof(uint8_t), sizeof(uint8_t) + } + }, + [RTE_FLOW_ITEM_TYPE_IPV6] = { + "ipv6", + dpaa2_flow_ip_extract_rule_set, + dpaa2_flow_general_tunnel_extract_rule_set, + DPAA2_PARSER_IPV6_ID, DPAA2_PARSER_TUNNEL_IPV6_ID, RTE_FLOW_ITEM_TYPE_IPV6, + &dpaa2_flow_item_ipv6_mask, sizeof(struct rte_flow_item_ipv6), + true, NET_PROT_IP, 3, + .fields = { + NH_FLD_IP_SRC, NH_FLD_IP_DST, NH_FLD_IP_PROTO + }, + .field_offset = { + offsetof(struct rte_flow_item_ipv6, hdr.src_addr), + offsetof(struct rte_flow_item_ipv6, hdr.dst_addr), + offsetof(struct rte_flow_item_ipv6, hdr.proto), + }, + .field_size = { + RTE_IPV6_ADDR_SIZE, RTE_IPV6_ADDR_SIZE, sizeof(uint8_t) + } + }, + [RTE_FLOW_ITEM_TYPE_VXLAN] = { + "vxlan", + dpaa2_flow_vxlan_extract_rule_set, + NULL, + DPAA2_PARSER_VXLAN_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_VXLAN, + &dpaa2_flow_item_vxlan_mask, sizeof(struct rte_flow_item_vxlan), + }, + [RTE_FLOW_ITEM_TYPE_ECPRI] = { + "ecpri", + dpaa2_flow_ecpri_extract_rule_set, + NULL, + DPAA2_PARSER_ECPRI_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_ECPRI, + &dpaa2_flow_item_ecpri_mask, sizeof(struct rte_flow_item_ecpri), + }, + [RTE_FLOW_ITEM_TYPE_GENEVE] = { + "geneve", + dpaa2_flow_geneve_extract_rule_set, + NULL, + DPAA2_PARSER_GENEVE_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_GENEVE, + &dpaa2_flow_item_geneve_mask, sizeof(struct rte_flow_item_geneve), + }, + [RTE_FLOW_ITEM_TYPE_RAW] = { + "raw", + dpaa2_flow_raw_extract_rule_set, + NULL, + DPAA2_PARSER_NULL_ID, DPAA2_PARSER_NULL_ID, RTE_FLOW_ITEM_TYPE_RAW } +}; - if (memcmp((const char *)&mask_ipv6->hdr.dst_addr, zero_cmp, NH_FLD_IPV6_ADDR_SIZE)) { - key = &spec_ipv6->hdr.dst_addr; - mask = &mask_ipv6->hdr.dst_addr; - size = NH_FLD_IPV6_ADDR_SIZE; - - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; +static inline bool +dpaa2_flow_is_qos_flow_only(struct dpaa2_dev_priv *priv, + uint32_t group) +{ + if ((priv->flags & DPAA2_QOS_FLOW_ONLY_STEER_FLAG) || !priv->fs_entries || + RTE_DPAA2_FLOW_GROUP_TYPE_GET(group) == RTE_DPAA2_QOS_GROUP_FLOW) + return true; - ret = dpaa2_flow_add_ipaddr_extract_rule(flow, NET_PROT_IPV6, - NH_FLD_IPV6_DST_IP, - key, mask, size, priv, - group, &local_cfg, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } + return false; +} - if (mask_ipv6->hdr.proto) { - key = &spec_ipv6->hdr.proto; - mask = &mask_ipv6->hdr.proto; - size = sizeof(uint8_t); +static inline uint8_t +dpaa2_flow_entry_map_get(const uint8_t *entry_map, uint16_t index) +{ + uint16_t byte_pos = index / 8; + uint16_t bit_pos = index % 8; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; + return entry_map[byte_pos] & (1 << bit_pos); +} - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IP, - NH_FLD_IP_PROTO, key, - mask, size, priv, group, - &local_cfg, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } +static inline void +dpaa2_flow_entry_map_set(uint8_t *entry_map, + uint16_t index, int set) +{ + uint16_t byte_pos = index / 8; + uint16_t bit_pos = index % 8; - (*device_configured) |= local_cfg; - return 0; + if (set) + entry_map[byte_pos] |= (1 << bit_pos); + else + entry_map[byte_pos] &= ~(((uint8_t)1) << bit_pos); } -static int -dpaa2_configure_flow_icmp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +static void +dpaa2_flow_generic_flow_deinit(struct dpaa2_generic_flow *flow) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_icmp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; + if (!flow) + return; - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_icmp_mask; + if (flow->key_addr) + rte_free(flow->key_addr); + if (flow->mask_addr) + rte_free(flow->mask_addr); + rte_free(flow); +} - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; +static struct dpaa2_generic_flow * +dpaa2_flow_generic_flow_init(struct dpaa2_dev_priv *priv, uint16_t idx, int no_key, + enum dpaa2_flow_dist_type type, uint8_t tc_id) +{ + struct dpaa2_generic_flow *flow = NULL; + uint64_t iova; - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ICMP distribution not support"); - return -ENOTSUP; + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_generic_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + DPAA2_PMD_ERR("Failure to allocate flow memory"); + goto mem_failure; } + flow->type = type; + flow->tc_id = tc_id; + flow->priv = priv; - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ICMP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_ICMP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + if (no_key) + return flow; - (*device_configured) |= local_cfg; - return 0; + /* Allocate DMA'ble memory to write the qos rules */ + flow->key_addr = rte_zmalloc(NULL, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, 0); + if (!flow->key_addr) { + DPAA2_PMD_ERR("Failure to allocate flow key memory"); + goto mem_failure; } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ICMP); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ICMP not support."); - - return ret; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->key_addr, + DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + if (iova == RTE_BAD_IOVA) { + DPAA2_PMD_ERR("Failure to map for key(%p)", flow->key_addr); + goto mem_failure; } + flow->rule_cfg.key_iova = iova; - if (mask->hdr.icmp_type) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type, - &mask->hdr.icmp_type, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_TYPE, &spec->hdr.icmp_type, - &mask->hdr.icmp_type, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + flow->mask_addr = rte_zmalloc(NULL, DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, 0); + if (!flow->mask_addr) { + DPAA2_PMD_ERR("Failure to allocate flow mask memory"); + goto mem_failure; } - - if (mask->hdr.icmp_code) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_CODE, &spec->hdr.icmp_code, - &mask->hdr.icmp_code, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_ICMP, - NH_FLD_ICMP_CODE, &spec->hdr.icmp_code, - &mask->hdr.icmp_code, sizeof(uint8_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->mask_addr, + DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + if (iova == RTE_BAD_IOVA) { + DPAA2_PMD_ERR("Failure to map for mask(%p)", flow->mask_addr); + goto mem_failure; } + flow->rule_cfg.mask_iova = iova; + flow->ip_key = NET_PROT_NONE; + flow->entry_index = idx; - (*device_configured) |= local_cfg; + return flow; - return 0; +mem_failure: + dpaa2_flow_generic_flow_deinit(flow); + + return NULL; } -static int -dpaa2_configure_flow_udp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_flow_group_set_miss_actions, 23.11) +int +rte_dpaa2_flow_group_set_miss_actions(uint16_t port_id, + uint32_t group_id, uint32_t type, const struct rte_flow_group_attr *attr, + const struct rte_flow_action actions[], struct rte_flow_error *error) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_udp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_udp_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - if (spec) { - DPAA2_PMD_ERR("Tunnel-UDP distribution not support"); - return -ENOTSUP; - } - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_UDP_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_UDP_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; - } - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_UDP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_UDP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - if (!spec) { - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_UDP); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of UDP not support."); - - return ret; - } - - if (mask->hdr.src_port) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; + RTE_DPAA2_FLOW_GROUP_TYPE_SET(group_id, type); + return rte_flow_group_set_miss_actions(port_id, + group_id, attr, actions, error); +} - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } +static inline void +dpaa2_flow_extracts_log(const struct dpaa2_dev_priv *priv, + const char *prefix, uint8_t tc_id) +{ + const struct dpaa2_flow_tbl_profile *tbl_profile; + const struct dpaa2_key_profile *key_profile; - if (mask->hdr.dst_port) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; + if (!(priv->flags & DPAA2_FLOW_API_DEBUG_FLAG)) + return; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_UDP, - NH_FLD_UDP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } + tbl_profile = tc_id >= MAX_TCS ? + &priv->flow_profile.qos_profile : &priv->flow_profile.tc_profile[tc_id]; + key_profile = &tbl_profile->key_profile; - (*device_configured) |= local_cfg; + DPAA2_FLOW_DUMP("%s %s's", prefix, priv->eth_dev->data->name); + if (tc_id >= MAX_TCS) + DPAA2_FLOW_DUMP(" QoS"); + else + DPAA2_FLOW_DUMP(" FS[%d]", tc_id); - return 0; + DPAA2_FLOW_DUMP(" table: %d extracts/%d entries\n", + key_profile->dpkg.num_extracts, tbl_profile->entry_num); + dpaa2_dump_dpkg(&key_profile->dpkg); } -static int -dpaa2_configure_flow_tcp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +static inline void +dpaa2_flow_steering_entry_log(const char *log_info, + const struct dpaa2_generic_flow *flow) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_tcp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_tcp_mask; + int idx; + struct rte_eth_dev *dev = flow->priv->eth_dev; + const struct dpaa2_dev_fs_action *fs_action = &flow->fs_action; + const struct dpni_fs_action_cfg *fs_cfg = &fs_action->action_cfg; - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + if (!(flow->priv->flags & DPAA2_FLOW_API_DEBUG_FLAG)) + return; - if (dpaa2_pattern->in_tunnel) { - if (spec) { - DPAA2_PMD_ERR("Tunnel-TCP distribution not support"); - return -ENOTSUP; + if (flow->type == DPAA2_FLOW_QOS_TYPE) { + DPAA2_FLOW_DUMP("%s: %s QoS entry[%d](size %d/%d) to select TC[%d]", + dev->data->name, log_info, flow->entry_index, flow->rule_size, + flow->rule_cfg.key_size, flow->tc_id); + } else { + DPAA2_FLOW_DUMP("%s: %s FS[%d]/entry[%d](size %d/%d)", + dev->data->name, log_info, flow->tc_id, + flow->entry_index, flow->rule_size, + flow->rule_cfg.key_size); + } + + DPAA2_FLOW_DUMP("\nkey: "); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->key_addr[idx]); + if (flow->rule_size > 0) + DPAA2_FLOW_DUMP("\n"); + + DPAA2_FLOW_DUMP("mask:"); + for (idx = 0; idx < flow->rule_size; idx++) + DPAA2_FLOW_DUMP("%02x ", flow->mask_addr[idx]); + if (flow->rule_size > 0) + DPAA2_FLOW_DUMP("\n"); + DPAA2_FLOW_DUMP("Action: "); + if (flow->type == DPAA2_FLOW_QOS_TYPE) { + if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) + DPAA2_FLOW_DUMP("Receive to flow%d", fs_cfg->flow_id); + else if (flow->action_type == RTE_FLOW_ACTION_TYPE_JUMP) + DPAA2_FLOW_DUMP("Jump to TC%d", flow->tc_id); + else + DPAA2_FLOW_DUMP("Un-supported QoS action type(%d)", flow->action_type); + } else { + if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { + DPAA2_FLOW_DUMP("Receive to flow%d", fs_cfg->flow_id); + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || + flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { + DPAA2_FLOW_DUMP("Re-direct to port(s): "); + for (idx = 0; idx < fs_cfg->num_tokens; idx++) { + DPAA2_FLOW_DUMP("%s", fs_action->dst_name[idx]); + if ((idx + 1) < fs_action->action_cfg.num_tokens) + DPAA2_FLOW_DUMP(", "); + } + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + DPAA2_FLOW_DUMP("Drop"); + } else { + DPAA2_FLOW_DUMP("Un-supported FS action type(%d)", flow->action_type); } - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_TCP_FRAM, - DPAA2_FLOW_QOS_TYPE, group, - &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_VXLAN_IN_TCP_FRAM, - DPAA2_FLOW_FS_TYPE, group, - &local_cfg); - return ret; } + DPAA2_FLOW_DUMP("\n"); +} - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_TCP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; +static inline void +dpaa2_dump_extract_map(const struct dpaa2_dev_priv *priv, + const char *prefix, enum dpaa2_flow_dist_type dist_type, + uint8_t group) +{ + int idx, avail, end = 0; + const struct dpaa2_flow_tbl_profile *tbl_profile; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_TCP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + if (!(priv->flags & DPAA2_FLOW_API_DEBUG_FLAG)) + return; - if (!spec) { - (*device_configured) |= local_cfg; - return 0; - } + DPAA2_FLOW_DUMP("%s: %s\n", priv->eth_dev->data->name, prefix); - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_TCP); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of TCP not support."); + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + DPAA2_FLOW_DUMP("QoS entry map:"); + if (!tbl_profile->entry_num) { + DPAA2_FLOW_DUMP(" empty\n"); + goto qos_dump_end; + } + DPAA2_FLOW_DUMP("\n"); + for (idx = 0; idx < priv->qos_entries; idx++) { + avail = 0; + end = 0; + if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx)) + avail = 1; + DPAA2_FLOW_DUMP("%d ", avail); + if (!((idx + 1) % 16) || (idx + 1) == priv->qos_entries) { + end = 1; + DPAA2_FLOW_DUMP("\n"); + } + } - return ret; +qos_dump_end: + goto flush_string; } - if (mask->hdr.src_port) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + tbl_profile = &priv->flow_profile.tc_profile[group]; + if (!tbl_profile->entry_num) { + DPAA2_FLOW_DUMP("FS[%d] table is empty\n", group); + return; } - if (mask->hdr.dst_port) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_TCP, - NH_FLD_TCP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + DPAA2_FLOW_DUMP("FS[%d] %d entries:\n", group, tbl_profile->entry_num); + for (idx = 0; idx < priv->fs_entries; idx++) { + avail = 0; + end = 0; + if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, idx)) + avail = 1; + DPAA2_FLOW_DUMP("%d ", avail); + if (!((idx + 1) % 16) || (idx + 1) == priv->fs_entries) { + end = 1; + DPAA2_FLOW_DUMP("\n"); + } } - - (*device_configured) |= local_cfg; - - return 0; +flush_string: + if (!end) + DPAA2_FLOW_DUMP("\n"); } static int -dpaa2_configure_flow_esp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_rss_conf_to_item(uint64_t req_dist_set, + struct rte_flow_item *items, uint8_t *spec_buf, + uint32_t buf_max) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_esp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_esp_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ESP distribution not support"); + uint32_t i = 0, offset = 0; + uint64_t l2_mask, vlan_mask, ipv4_mask, ipv6_mask; + uint64_t dist_supported, udp_mask, tcp_mask, sctp_mask; + struct rte_flow_item_eth *eth = NULL; + struct rte_flow_item_pppoe *pppoe = NULL; + struct rte_flow_item_esp *esp = NULL; + struct rte_flow_item_ah *ah = NULL; + struct rte_flow_item_vlan *vlan = NULL; + struct rte_flow_item_mpls *mpls = NULL; + struct rte_flow_item_gtp *gtpu = NULL; + struct rte_flow_item_udp *udp = NULL; + struct rte_flow_item_tcp *tcp = NULL; + struct rte_flow_item_sctp *sctp = NULL; + struct rte_flow_item_ipv4 *ipv4 = NULL; + + l2_mask = RTE_ETH_RSS_L2_PAYLOAD | RTE_ETH_RSS_ETH; + vlan_mask = RTE_ETH_RSS_C_VLAN | RTE_ETH_RSS_S_VLAN; + ipv4_mask = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | + RTE_ETH_RSS_NONFRAG_IPV4_OTHER; + ipv6_mask = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | + RTE_ETH_RSS_IPV6_EX| RTE_ETH_RSS_NONFRAG_IPV6_OTHER; + udp_mask = RTE_ETH_RSS_NONFRAG_IPV4_UDP | + RTE_ETH_RSS_NONFRAG_IPV6_UDP | + RTE_ETH_RSS_IPV6_UDP_EX; + tcp_mask = RTE_ETH_RSS_NONFRAG_IPV4_TCP | + RTE_ETH_RSS_NONFRAG_IPV6_TCP | + RTE_ETH_RSS_IPV6_TCP_EX; + sctp_mask = RTE_ETH_RSS_NONFRAG_IPV4_SCTP | + RTE_ETH_RSS_NONFRAG_IPV6_SCTP; + dist_supported = l2_mask | vlan_mask | ipv4_mask | + ipv6_mask | udp_mask | tcp_mask | sctp_mask | + RTE_ETH_RSS_GTPU | RTE_ETH_RSS_PPPOE | + RTE_ETH_RSS_ESP | RTE_ETH_RSS_AH | RTE_ETH_RSS_MPLS; + if ((~dist_supported) & req_dist_set) { + DPAA2_PMD_ERR("%s: Unsupported dist type:0x%lx", + __func__, (~dist_supported) & req_dist_set); return -ENOTSUP; } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_ESP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - if (!spec) { - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ESP); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ESP not support."); - - return ret; - } - - if (mask->hdr.spi) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi, - &mask->hdr.spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SPI, &spec->hdr.spi, - &mask->hdr.spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + if (req_dist_set & l2_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_ETH; + eth = (void *)(spec_buf + offset); + memset(eth, 0, sizeof(struct rte_flow_item_eth)); + memset(eth->dst.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN); + memset(eth->src.addr_bytes, 0xff, RTE_ETHER_ADDR_LEN); + eth->type = RTE_BE16(0xffff); + items[i].spec = eth; + items[i].mask = eth; + i++; + offset += sizeof(struct rte_flow_item_eth); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_PPPOE) { + items[i].type = RTE_FLOW_ITEM_TYPE_PPPOES; + pppoe = (void *)(spec_buf + offset); + memset(pppoe, 0, sizeof(struct rte_flow_item_pppoe)); + pppoe->session_id = RTE_BE16(0xffff); + items[i].spec = pppoe; + items[i].mask = pppoe; + i++; + offset += sizeof(struct rte_flow_item_pppoe); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_ESP) { + items[i].type = RTE_FLOW_ITEM_TYPE_ESP; + esp = (void *)(spec_buf + offset); + memset(esp, 0, sizeof(struct rte_flow_item_esp)); + esp->hdr.spi = RTE_BE32(0xffffffff); + items[i].spec = esp; + items[i].mask = esp; + i++; + offset += sizeof(struct rte_flow_item_esp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_AH) { + items[i].type = RTE_FLOW_ITEM_TYPE_AH; + ah = (void *)(spec_buf + offset); + memset(ah, 0, sizeof(struct rte_flow_item_ah)); + ah->spi = RTE_BE32(0xffffffff); + items[i].spec = ah; + items[i].mask = ah; + i++; + offset += sizeof(struct rte_flow_item_ah); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & vlan_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_VLAN; + vlan = (void *)(spec_buf + offset); + memset(vlan, 0, sizeof(struct rte_flow_item_vlan)); + vlan->tci = RTE_BE16(0xffff); + items[i].spec = vlan; + items[i].mask = vlan; + i++; + offset += sizeof(struct rte_flow_item_vlan); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_MPLS) { + items[i].type = RTE_FLOW_ITEM_TYPE_MPLS; + mpls = (void *)(spec_buf + offset); + memset(mpls, 0, sizeof(struct rte_flow_item_mpls)); + memset(mpls->label_tc_s, 0xff, 3); + items[i].spec = mpls; + items[i].mask = mpls; + i++; + offset += sizeof(struct rte_flow_item_mpls); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & RTE_ETH_RSS_GTPU) { + items[i].type = RTE_FLOW_ITEM_TYPE_GTPU; + gtpu = (void *)(spec_buf + offset); + memset(gtpu, 0, sizeof(struct rte_flow_item_gtp)); + gtpu->teid = RTE_BE32(0xffffffff); + items[i].spec = gtpu; + items[i].mask = gtpu; + i++; + offset += sizeof(struct rte_flow_item_gtp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & udp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_UDP; + udp = (void *)(spec_buf + offset); + memset(udp, 0, sizeof(struct rte_flow_item_udp)); + udp->hdr.src_port = RTE_BE16(0xffff); + udp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = udp; + items[i].mask = udp; + i++; + offset += sizeof(struct rte_flow_item_udp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & tcp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_TCP; + tcp = (void *)(spec_buf + offset); + memset(tcp, 0, sizeof(struct rte_flow_item_tcp)); + tcp->hdr.src_port = RTE_BE16(0xffff); + tcp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = tcp; + items[i].mask = tcp; + i++; + offset += sizeof(struct rte_flow_item_tcp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & sctp_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_SCTP; + sctp = (void *)(spec_buf + offset); + memset(sctp, 0, sizeof(struct rte_flow_item_sctp)); + sctp->hdr.src_port = RTE_BE16(0xffff); + sctp->hdr.dst_port = RTE_BE16(0xffff); + items[i].spec = sctp; + items[i].mask = sctp; + i++; + offset += sizeof(struct rte_flow_item_sctp); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; + } + + if (req_dist_set & ipv4_mask) { + items[i].type = RTE_FLOW_ITEM_TYPE_IPV4; + ipv4 = (void *)(spec_buf + offset); + memset(ipv4, 0, sizeof(struct rte_flow_item_ipv4)); + ipv4->hdr.src_addr = RTE_BE32(0xffffffff); + ipv4->hdr.dst_addr = RTE_BE32(0xffffffff); + ipv4->hdr.next_proto_id = 0xff; + items[i].spec = ipv4; + items[i].mask = ipv4; + i++; + offset += sizeof(struct rte_flow_item_ipv4); + offset = RTE_CACHE_LINE_ROUNDUP(offset); + if (offset > buf_max) + return -ENOMEM; } - if (mask->hdr.seq) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq, - &mask->hdr.seq, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_ESP, - NH_FLD_IPSEC_ESP_SEQUENCE_NUM, &spec->hdr.seq, - &mask->hdr.seq, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } + items[i].type = RTE_FLOW_ITEM_TYPE_END; - (*device_configured) |= local_cfg; + return i; +} - return 0; +static inline int +dpaa2_flow_is_steering_flow(struct dpaa2_generic_flow *flow) +{ + if (flow->type & (DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE)) + return true; + return false; } static int -dpaa2_configure_flow_ah(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_add_steering_rule(struct dpaa2_generic_flow *flow, int update) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ah *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - group = attr->group; + struct dpaa2_dev_priv *priv = flow->priv; + struct dpaa2_flow_tbl_profile *tbl_profile; + int ret; + struct fsl_mc_io *dpni = priv->hw; + uint8_t flags = DPNI_QOS_OPT_SET_TC_ONLY; + struct dpni_fs_action_cfg action_cfg; - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_ah_mask; + if (!dpaa2_flow_is_steering_flow(flow)) { + DPAA2_PMD_ERR("%s: flow(type=%x) is not steering flow", + __func__, flow->type); + return -EINVAL; + } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + rte_memcpy(&action_cfg, &flow->fs_action, sizeof(action_cfg)); + if (update) { + flags |= DPNI_QOS_OPT_UPDATE_IF_EXISTS; + action_cfg.options |= DPNI_FS_OPT_UPDATE_IF_EXISTS; + } - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-AH distribution not support"); - return -ENOTSUP; + if (!update) { + if (flow->type == DPAA2_FLOW_QOS_TYPE) + tbl_profile = &priv->flow_profile.qos_profile; + else + tbl_profile = &priv->flow_profile.tc_profile[flow->tc_id]; + if (dpaa2_flow_entry_map_get(tbl_profile->entry_map, flow->entry_index)) { + DPAA2_PMD_ERR("%s table's rule(%d) exists.", + flow->type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS", + flow->entry_index); + dpaa2_dump_extract_map(priv, "Entry conflicts!", flow->type, flow->tc_id); + return -EINVAL; + } } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_AH_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + dpaa2_flow_steering_entry_log(update ? "Update" : "Add", flow); - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_IPSEC_AH_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) + if (flow->type == DPAA2_FLOW_QOS_TYPE) { + if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) + flags |= DPNI_QOS_OPT_SET_FLOW_ID; + ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, + priv->token, &flow->rule_cfg, flow->tc_id, + flow->entry_index, flags, action_cfg.flow_id); + } else if (priv->mc_rev >= DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV) { + ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, &action_cfg); + } else { + ret = dpni_add_fs_entry_legacy(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, flow->entry_index, + &flow->rule_cfg, &action_cfg); + } + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to %s rule(%d) to %s table", + ret, update ? "Update" : "Add", flow->entry_index, + flow->type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS"); return ret; + } - if (!spec) { - (*device_configured) |= local_cfg; - return 0; + if (!update) { + dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 1); + tbl_profile->entry_num++; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_AH); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of AH not support."); + return 0; +} - return ret; - } +static int +dpaa2_flow_add_all_steering_rule(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type dist_type, uint16_t entry_size, uint8_t tc_id) +{ + struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); + struct dpaa2_generic_flow *flow; + int ret; - if (mask->spi) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH, - NH_FLD_IPSEC_AH_SPI, &spec->spi, - &mask->spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; + if (dist_type != DPAA2_FLOW_QOS_TYPE && dist_type != DPAA2_FLOW_FS_TYPE) + return -EINVAL; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_IPSEC_AH, - NH_FLD_IPSEC_AH_SPI, &spec->spi, - &mask->spi, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + while (curr) { + flow = dpaa2_flow_generic_flow(curr, dist_type, tc_id); + if (!flow) + goto next_flow; + flow->rule_cfg.key_size = entry_size; + ret = dpaa2_flow_add_steering_rule(flow, false); if (ret) return ret; +next_flow: + curr = LIST_NEXT(curr, next); } - if (mask->seq_num) { - DPAA2_PMD_ERR("AH seq distribution not support"); - return -ENOTSUP; - } + return 0; +} + +static inline int +dpaa2_flow_verify_steering_entry(struct dpaa2_dev_priv *priv, + uint16_t tc, uint16_t entry_idx, enum dpaa2_flow_dist_type dist_type) +{ + struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); + struct dpaa2_generic_flow *flow; - (*device_configured) |= local_cfg; + while (curr) { + flow = dpaa2_flow_generic_flow(curr, dist_type, tc); + if (flow && flow->entry_index == entry_idx) { + if (dist_type == DPAA2_FLOW_QOS_TYPE) + DPAA2_PMD_ERR("Flow QoS.entry[%d] exists", entry_idx); + else if (dist_type == DPAA2_FLOW_FS_TYPE) + DPAA2_PMD_ERR("Flow TC[%d].entry[%d] exists", tc, entry_idx); + else + DPAA2_PMD_ERR("It is not steering flow(type=%x)", dist_type); + return -EEXIST; + } + curr = LIST_NEXT(curr, next); + } return 0; } -static int -dpaa2_configure_flow_sctp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +static inline struct rte_eth_dev * +dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv, + const struct rte_flow_action *action) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_sctp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + const struct rte_flow_action_port_id *port_id; + const struct rte_flow_action_ethdev *ethdev; + int idx = -1; + struct rte_eth_dev *dest_dev; - group = attr->group; + if (action->type == RTE_FLOW_ACTION_TYPE_PORT_ID) { + port_id = action->conf; + if (!port_id->original) + idx = port_id->id; + } else if (action->type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { + ethdev = action->conf; + idx = ethdev->port_id; + } else { + return NULL; + } - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_sctp_mask; + if (idx >= 0) { + if (!rte_eth_dev_is_valid_port(idx)) + return NULL; + if (!rte_pmd_dpaa2_dev_is_dpaa2(idx)) + return NULL; + dest_dev = &rte_eth_devices[idx]; + } else { + dest_dev = priv->eth_dev; + } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + return dest_dev; +} - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-SCTP distribution not support"); - return -ENOTSUP; - } +static inline int +dpaa2_flow_verify_flow_action(struct dpaa2_dev_priv *priv, + const struct rte_flow_attr *attr, + const struct rte_flow_action actions[]) +{ + int end_of_list = 0, i, j = 0; + const struct rte_flow_action_queue *dest_queue; + const struct rte_flow_action_rss *rss_conf; + const struct rte_flow_action_jump *jump_tc; + struct dpaa2_queue *rxq; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_SCTP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + while (!end_of_list) { + switch (actions[j].type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_SCTP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + return -EINVAL; + } + rxq = priv->rx_vq[dest_queue->index]; + if (attr->group != rxq->tc_index) { + DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", + rxq->tc_index, rxq->flow_id, + attr->group); - if (!spec) { - (*device_configured) |= local_cfg; - return 0; + return -EINVAL; + } + break; + case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: + case RTE_FLOW_ACTION_TYPE_PORT_ID: + if (!dpaa2_flow_redirect_dev(priv, &actions[j])) { + DPAA2_PMD_ERR("Invalid port id of action"); + return -EINVAL; + } + break; + case RTE_FLOW_ACTION_TYPE_JUMP: + jump_tc = actions[j].conf; + if (jump_tc->group >= priv->num_rx_tc) { + DPAA2_PMD_ERR("Invalid tc(%d) > %d to jump", + jump_tc->group, priv->num_rx_tc); + return -EINVAL; + } + break; + case RTE_FLOW_ACTION_TYPE_RSS: + rss_conf = actions[j].conf; + if (rss_conf->queue_num > priv->dist_queues) { + DPAA2_PMD_ERR("RSS number too large"); + return -EINVAL; + } + if (rss_conf->queue) { + for (i = 0; i < (int)rss_conf->queue_num; i++) { + if (rss_conf->queue[i] >= priv->nb_rx_queues) { + DPAA2_PMD_ERR("RSS queue not in range"); + return -EINVAL; + } + rxq = priv->rx_vq[rss_conf->queue[i]]; + if (rxq->tc_index != attr->group) { + DPAA2_PMD_ERR("RSS queue not in group"); + return -EINVAL; + } + } + } + + break; + case RTE_FLOW_ACTION_TYPE_PF: + /* Skip this action, have to add for vxlan*/ + case RTE_FLOW_ACTION_TYPE_DROP: + break; + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_ERR("Invalid action[%d] type(%d)", j, actions[j].type); + return -EINVAL; + } + j++; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_SCTP); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of SCTP not support."); + return 0; +} - return ret; - } +static int +dpaa2_flow_action_rxq_convert(struct dpaa2_generic_flow *flow, + const struct rte_flow_action *rte_action) +{ + struct dpaa2_dev_priv *priv = flow->priv; + struct dpaa2_dev_fs_action *action = &flow->fs_action; + const struct rte_flow_action_queue *dest_queue; + struct dpaa2_queue *dest_q; + uint64_t flc = 0; - if (mask->hdr.src_port) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; + dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid rxq index(%d)", dest_queue->index); - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_SRC, &spec->hdr.src_port, - &mask->hdr.src_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + return -EINVAL; } + dest_q = priv->rx_vq[dest_queue->index]; + if (dest_q->tc_index != flow->tc_id && flow->type == DPAA2_FLOW_FS_TYPE) { + DPAA2_PMD_ERR("rxq index(%d)'s TC(%d) conflicts with FS flow's TC(%d)", + dest_queue->index, dest_q->tc_index, flow->tc_id); - if (mask->hdr.dst_port) { - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_SCTP, - NH_FLD_SCTP_PORT_DST, &spec->hdr.dst_port, - &mask->hdr.dst_port, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + return -EINVAL; } - (*device_configured) |= local_cfg; + flow->tc_id = dest_q->tc_index; + flow->action_type = RTE_FLOW_ACTION_TYPE_QUEUE; + action->action_cfg.options = DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + if (dest_q->data_stashing_off) + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &flc); + else + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 1, &flc); + + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, 1, &flc); + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + action->action_cfg.flc = flc; + action->action_cfg.flow_id = dest_q->flow_id; return 0; } static int -dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_action_tx_port_convert(struct dpaa2_generic_flow *flow, + const struct rte_flow_action *rte_action) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_gre *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; + struct dpaa2_dev_priv *priv = flow->priv; + struct dpaa2_dev_fs_action *action = &flow->fs_action; + struct rte_eth_dev *dest_dev; + struct dpaa2_dev_priv *dest_priv; + uint16_t num_tokens; - group = attr->group; + if (flow->action_type != RTE_FLOW_ACTION_TYPE_END && + !(priv->options & DPNI_OPT_V8_HAS_REPLICATION)) { + DPAA2_PMD_ERR("Single tx port action support only."); + return -ENOTSUP; + } + num_tokens = action->action_cfg.num_tokens; + if (num_tokens >= DPNI_FS_REDIR_MAX_NUM) + return -EINVAL; - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_gre_mask; + dest_dev = dpaa2_flow_redirect_dev(priv, rte_action); + if (!dest_dev) { + DPAA2_PMD_ERR("Invalid device to redirect"); + return -EINVAL; + } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + flow->action_type = rte_action->type; - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-GRE distribution not support"); - return -ENOTSUP; - } + dest_priv = dest_dev->data->dev_private; + action->action_cfg.redir_tokens[num_tokens] = dest_priv->token; + rte_strscpy(action->dst_name[num_tokens], dest_priv->eth_dev->data->name, + RTE_ETH_NAME_MAX_LEN); + action->action_cfg.num_tokens++; + if (action->action_cfg.num_tokens > 1) + action->action_cfg.options = DPNI_FS_OPT_REDIRECT_TO_MULTIPLE_DPNI_TX; + else + action->action_cfg.options = DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GRE_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + return 0; +} - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GRE_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; +static inline uint16_t +dpaa2_flow_entry_size(uint16_t key_max_size) +{ + if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { + DPAA2_PMD_ERR("Key size(%d) > max(%d)", + key_max_size, + DPAA2_FLOW_ENTRY_MAX_SIZE); - (*device_configured) |= local_cfg; return 0; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_GRE); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of GRE not support."); + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + return DPAA2_FLOW_ENTRY_MAX_SIZE; - return ret; - } + return DPAA2_FLOW_ENTRY_MIN_SIZE; +} - if (!mask->protocol) +static int +dpaa2_flow_fs_table_set_default(struct dpaa2_dev_priv *priv, + uint8_t tc_id, int discard, uint16_t default_queue) +{ + int ret; + struct dpni_rx_dist_cfg *tc_cfg; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_queue *queue; + char mc_rev[1024]; + + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", + RTE_FSL_MC_REV_MAJOR(priv->mc_rev), + RTE_FSL_MC_REV_MINOR(priv->mc_rev), + RTE_FSL_MC_REV_REVISION(priv->mc_rev)); + if (!tbl_profile->key_profile.dpkg.num_extracts && + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + DPAA2_PMD_DEBUG("%s can't set miss action of FS table indepentently.", + mc_rev); return 0; + } + tc_cfg = &tbl_profile->tc_cfg; + tc_cfg->enable = true; + if (discard) { + tbl_profile->default_drop = true; + tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP; + } else { + if (default_queue >= MAX_RX_QUEUES || !priv->rx_vq[default_queue]) { + DPAA2_PMD_ERR("Invalid default queue index(%d)", default_queue); - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE, - NH_FLD_GRE_TYPE, &spec->protocol, - &mask->protocol, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GRE, - NH_FLD_GRE_TYPE, &spec->protocol, - &mask->protocol, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) + return -EINVAL; + } + queue = priv->rx_vq[default_queue]; + if (queue->tc_index != tc_id) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + default_queue, queue->tc_index, queue->flow_id, tc_id); + return -EINVAL; + } + tbl_profile->default_drop = false; + tbl_profile->default_queue.index = default_queue; + tc_cfg->fs_miss_flow_id = queue->flow_id; + } + ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("%s: Failed(%d) to set default action of TC[%d]", + __func__, ret, tc_id); return ret; - - (*device_configured) |= local_cfg; + } return 0; } static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_tc_table_config(struct dpaa2_dev_priv *priv, + uint8_t tc_id, int rss_dist, int enable) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } + struct dpaa2_flow_tbl_profile *tbl_profile; + struct dpaa2_key_profile *key_profile; + int ret; + struct dpni_rx_dist_cfg *tc_cfg; + struct fsl_mc_io *dpni = priv->hw; + uint16_t entry_size; + struct dpaa2_queue *queue; - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + if (tbl_profile->entry_num) { + ret = dpni_clear_fs_entries(dpni, CMD_PRI_LOW, priv->token, tc_id); + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to clear FS of TC[%d]", ret, tc_id); return ret; + } + } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + tbl_profile->entry_num = 0; + memset(tbl_profile->entry_map, 0, tbl_profile->entry_map_size); + key_profile = &tbl_profile->key_profile; + entry_size = dpaa2_flow_entry_size(key_profile->key_max_size); + if (!key_profile->dpkg.num_extracts) { + enable = false; + goto table_set; + } - (*device_configured) |= local_cfg; - return 0; + dpaa2_flow_extracts_log(priv, "Configure", tc_id); + ret = dpkg_prepare_key_cfg(&key_profile->dpkg, tbl_profile->extract_param); + if (ret < 0) { + DPAA2_PMD_ERR("TC[%d] prepare key failed", tc_id); + return ret; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); +table_set: + tc_cfg = &tbl_profile->tc_cfg; + if (rss_dist) + tc_cfg->enable = enable; + else + tc_cfg->enable = false; + ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg); if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); + DPAA2_PMD_ERR("Failed(%d) to %s RSS of TC[%d]", + ret, rss_dist ? "configure" : "clear", tc_id); return ret; } + if (rss_dist) + goto successful_config; + + tc_cfg->enable = enable; + if (tbl_profile->default_drop) { + tc_cfg->fs_miss_flow_id = DPNI_FS_MISS_ACTION_DROP; + } else { + if (tbl_profile->default_queue.index >= MAX_RX_QUEUES || + !priv->rx_vq[tbl_profile->default_queue.index]) { + DPAA2_PMD_ERR("Invalid default queue index(%d)", + tbl_profile->default_queue.index); - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); return -EINVAL; } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); + queue = priv->rx_vq[tbl_profile->default_queue.index]; + if (queue->tc_index != tc_id) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + tbl_profile->default_queue.index, queue->tc_index, + queue->flow_id, tc_id); return -EINVAL; } + tc_cfg->fs_miss_flow_id = queue->flow_id; } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, tc_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("TC[%d] FS configured failed", tc_id); + return ret; } - (*device_configured) |= local_cfg; + ret = dpaa2_flow_add_all_steering_rule(priv, DPAA2_FLOW_FS_TYPE, entry_size, tc_id); + if (ret) + return ret; + +successful_config: + tbl_profile->enabled = true; return 0; } static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_qos_table_set_default(struct dpaa2_dev_priv *priv, + int discard, uint8_t default_tc, uint16_t default_flow) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; + int ret; + struct dpni_qos_tbl_cfg qos_cfg; + struct fsl_mc_io *dpni = priv->hw; + struct dpaa2_flow_tbl_profile *tbl_profile; + char mc_rev[1024]; + + tbl_profile = &priv->flow_profile.qos_profile; + snprintf(mc_rev, 1024, "MC rev(%d.%d.%d)", + RTE_FSL_MC_REV_MAJOR(priv->mc_rev), + RTE_FSL_MC_REV_MINOR(priv->mc_rev), + RTE_FSL_MC_REV_REVISION(priv->mc_rev)); + if (!tbl_profile->key_profile.dpkg.num_extracts && + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) { + DPAA2_PMD_DEBUG("%s can't set miss action of QoS table indepentently.", + mc_rev); + return 0; + } + if (default_flow < priv->dist_queues && + priv->mc_rev < DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV) { + DPAA2_PMD_WARN("%s can't direct miss traffic to TC%d-flow%d by QoS table only.", + mc_rev, default_tc, default_flow); + return 0; + } - group = attr->group; + rte_memcpy(&qos_cfg, &tbl_profile->qos_cfg, sizeof(struct dpni_qos_tbl_cfg)); + qos_cfg.key_cfg_iova = 0; + qos_cfg.default_tc = default_tc; + qos_cfg.default_flow_id = default_flow; + qos_cfg.discard_on_miss = discard ? true : false; + qos_cfg.set_default_flow_id = default_flow < priv->dist_queues ? true : false; - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; + ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, &qos_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("%s: Failed(%d) to set default action of QoS", + __func__, ret); + return ret; + } + if (discard) { + tbl_profile->default_drop = true; } else { - mask = &dpaa2_flow_item_ecpri_mask; + tbl_profile->default_drop = false; + tbl_profile->default_jump.group = default_tc; } + rte_memcpy(&tbl_profile->qos_cfg.discard_on_miss, + &qos_cfg.discard_on_miss, + sizeof(struct dpni_qos_tbl_cfg) - + offsetof(struct dpni_qos_tbl_cfg, discard_on_miss)); - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + return 0; +} - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } +static int +dpaa2_flow_qos_table_config(struct dpaa2_dev_priv *priv, + int rss_dist) +{ + struct dpaa2_flow_tbl_profile *tbl_profile; + uint8_t *key_cfg_buf; + int ret; + struct dpni_qos_tbl_cfg *qos_cfg; + struct fsl_mc_io *dpni = priv->hw; + uint16_t entry_size; + uint16_t key_max_size; + struct dpaa2_dev_flow *flow; - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + if (!rss_dist && priv->num_rx_tc <= 1) { + /* QoS table is effecitive for FS multiple TCs or RSS.*/ + return 0; + } - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) + tbl_profile = &priv->flow_profile.qos_profile; + flow = LIST_FIRST(&priv->flows); + while (flow) { + if (!flow->qos_flow) { + flow = LIST_NEXT(flow, next); + continue; + } + /** Clear existing QoS table if there is qos flow configured.*/ + ret = dpni_clear_qos_table(dpni, CMD_PRI_LOW, priv->token); + if (ret < 0) { + DPAA2_PMD_ERR("QoS table clear failed(%d)", ret); return ret; - - (*device_configured) |= local_cfg; - return 0; + } + tbl_profile->entry_num = 0; + memset(tbl_profile->entry_map, 0, tbl_profile->entry_map_size); + break; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); + if (!tbl_profile->key_profile.dpkg.num_extracts) + return 0; - return ret; - } + key_cfg_buf = tbl_profile->extract_param; + key_max_size = tbl_profile->key_profile.key_max_size; + entry_size = dpaa2_flow_entry_size(key_max_size); - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); + dpaa2_flow_extracts_log(priv, "Configure", MAX_TCS); - return -EINVAL; + ret = dpkg_prepare_key_cfg(&tbl_profile->key_profile.dpkg, key_cfg_buf); + if (ret < 0) { + DPAA2_PMD_ERR("QoS prepare extract failed"); + return ret; } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } + qos_cfg = &tbl_profile->qos_cfg; + if (rss_dist) { + qos_cfg->discard_on_miss = true; } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; + qos_cfg->default_tc = tbl_profile->default_jump.group; + if (tbl_profile->default_drop) + qos_cfg->discard_on_miss = true; + else + qos_cfg->discard_on_miss = false; } - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + if (priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) + ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, priv->token, qos_cfg); + else + ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, priv->token, qos_cfg); + if (ret < 0) { + DPAA2_PMD_ERR("QoS table set failed(%d)", ret); + return ret; } + tbl_profile->enabled = true; - (*device_configured) |= local_cfg; + ret = dpaa2_flow_add_all_steering_rule(priv, DPAA2_FLOW_QOS_TYPE, entry_size, 0); + if (ret) + return ret; return 0; } static int -dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_item_convert(const struct rte_flow_item pattern[], + struct dpaa2_flow_item **dpaa2_pattern, int sp_protocol) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_gtp *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; + struct dpaa2_flow_item *new_pattern; + int num = 0, tunnel_start = 0; - group = attr->group; + while (1) { + num++; + if (pattern[num].type == RTE_FLOW_ITEM_TYPE_END) + break; + } - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_gtp_mask; + new_pattern = rte_malloc(NULL, sizeof(struct dpaa2_flow_item) * num, + RTE_CACHE_LINE_SIZE); + if (!new_pattern) { + DPAA2_PMD_ERR("Failed to alloc %d flow items", num); + return -ENOMEM; + } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + num = 0; + while (pattern[num].type != RTE_FLOW_ITEM_TYPE_END) { + rte_memcpy(&new_pattern[num].item, &pattern[num], + sizeof(struct rte_flow_item)); + new_pattern[num].in_tunnel = 0; - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-GTP distribution not support"); - return -ENOTSUP; + if (pattern[num].type == RTE_FLOW_ITEM_TYPE_VXLAN) + tunnel_start = 1; + else if (tunnel_start && sp_protocol) + new_pattern[num].in_tunnel = 1; + num++; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GTP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + new_pattern[num].item.type = RTE_FLOW_ITEM_TYPE_END; + *dpaa2_pattern = new_pattern; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_GTP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; + return 0; +} - (*device_configured) |= local_cfg; - return 0; +static int +dpaa2_flow_table_update(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type dist_type, uint8_t tc_id, int is_rss) +{ + int ret; + + if (dist_type == DPAA2_FLOW_FS_TYPE || dist_type == DPAA2_FLOW_RSS_TYPE) { + ret = dpaa2_flow_tc_table_config(priv, tc_id, is_rss, true); + } else if (dist_type == DPAA2_FLOW_QOS_TYPE) { + ret = dpaa2_flow_qos_table_config(priv, false); + } else { + DPAA2_PMD_ERR("Invalid dist type(%d)!", dist_type); + ret = -EINVAL; } - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_GTP); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of GTP not support."); + return ret; +} - return ret; - } +static int +dpaa2_flow_steering_action_convert(struct dpaa2_generic_flow *flow, + const struct rte_flow_action actions[]) +{ + int end_of_list = 0, ret = 0, i = 0; + const struct rte_flow_action_jump *jump; - if (!mask->teid) - return 0; + if (!dpaa2_flow_is_steering_flow(flow)) { + DPAA2_PMD_ERR("%s: flow(type=%x) is not steering flow", + __func__, flow->type); + return -EINVAL; + } - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP, - NH_FLD_GTP_TEID, &spec->teid, - &mask->teid, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; + while (!end_of_list) { + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + ret = dpaa2_flow_action_rxq_convert(flow, &actions[i]); + if (ret) + goto end_action_set; + break; + case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: + case RTE_FLOW_ACTION_TYPE_PORT_ID: + ret = dpaa2_flow_action_tx_port_convert(flow, &actions[i]); + if (ret) + goto end_action_set; + break; + case RTE_FLOW_ACTION_TYPE_DROP: + flow->action_type = actions[i].type; + flow->fs_action.action_cfg.options = DPNI_FS_OPT_DISCARD; + break; + case RTE_FLOW_ACTION_TYPE_JUMP: + flow->action_type = actions[i].type; + jump = actions[i].conf; + flow->tc_id = jump->group; + break; + case RTE_FLOW_ACTION_TYPE_PF: + /* Skip this action, have to add for vxlan*/ + break; + case RTE_FLOW_ACTION_TYPE_END: + end_of_list = 1; + break; + default: + DPAA2_PMD_ERR("Invalid action[%d]'s type(%d)", i, actions[i].type); + ret = -ENOTSUP; + goto end_action_set; + } + i++; + } - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_GTP, - NH_FLD_GTP_TEID, &spec->teid, - &mask->teid, sizeof(rte_be32_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); +end_action_set: if (ret) return ret; - (*device_configured) |= local_cfg; + if (i < 1) { + DPAA2_PMD_ERR("No action is set!"); + return -EINVAL; + } return 0; } static int -dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_generic_extract_rule_set(struct dpaa2_generic_flow *flow, + const struct rte_flow_item pattern[], int *ecfg) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_mpls *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; + int ret, i = 0, index; + struct dpaa2_key_profile *key_profile = dpaa2_flow_key_profile(flow); + struct dpaa2_flow_item *dpaa2_pattern = NULL; + const struct dpaa2_flow_proto_handle *hd = s_dpaa2_flow_proto_handle; + + ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, flow->priv->sp_protocol); + if (ret) + return ret; - group = attr->group; + flow->ip_key = NET_PROT_NONE; + flow->ip_src = NET_PROT_NONE; + flow->ip_dst = NET_PROT_NONE; /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_mpls_mask; + while (pattern[i].type != RTE_FLOW_ITEM_TYPE_END) { + index = pattern[i].type; + if (!hd[index].name) { + DPAA2_PMD_ERR("Flow item[%d]'s type(%d) is not supported", + i, pattern[i].type); + ret = -ENOTSUP; + goto end_extract_set; + } + if (dpaa2_pattern[i].in_tunnel) { + if (hd[index].tunnel) + ret = hd[index].tunnel(flow, &dpaa2_pattern[i].item, &hd[index], ecfg); + else + ret = -ENOTSUP; + if (ret) + goto end_extract_set; + } + if (!hd[index].cb) { + DPAA2_PMD_ERR("No callback to configure %s flow", hd[index].name); + ret = -ENOTSUP; + goto end_extract_set; + } + ret = hd[index].cb(flow, &dpaa2_pattern[i].item, &hd[index], ecfg); + if (ret) { + DPAA2_PMD_ERR("Failed(%d) to configure %s flow", ret, hd[index].name); + goto end_extract_set; + } + i++; + } - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; + flow->rule_cfg.key_size = dpaa2_flow_entry_size(key_profile->key_max_size); - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); - return -ENOTSUP; +end_extract_set: + if (dpaa2_pattern) + rte_free(dpaa2_pattern); + + return ret; +} + +static int +dpaa2_flow_get_flow_index(struct dpaa2_dev_priv *priv, + const struct rte_flow_attr *attr, enum dpaa2_flow_dist_type dist_type, + uint16_t *index) +{ + uint16_t idx, id = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group); + + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + if (priv->flags & DPAA2_QOS_ENTRIES_PER_TC_FLAG) + idx = attr->group * priv->qos_entries_per_tc + attr->priority; + else + idx = id * priv->fs_entries + attr->priority; + + if (idx >= priv->qos_entries) { + DPAA2_PMD_ERR("QoS flow index(%d) >= max(%d)", idx, priv->qos_entries); + return -ENOSPC; + } + } else { + if (attr->priority >= priv->fs_entries) { + DPAA2_PMD_ERR("FS[%d].entry(%d) >= max(%d)", + attr->group, attr->priority, priv->fs_entries); + return -ENOSPC; + } + idx = attr->priority; } - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; + if (index) + *index = idx; + + return 0; +} + +static inline int +dpaa2_flow_verify_steering_attr(struct dpaa2_dev_priv *priv, + const struct rte_flow_attr *attr, enum dpaa2_flow_dist_type *pdist_type) +{ + int ret = 0; + enum dpaa2_flow_dist_type dist_type; + + if (dpaa2_flow_is_qos_flow_only(priv, attr->group)) + dist_type = DPAA2_FLOW_QOS_TYPE; + else if (RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr->group) == RTE_DPAA2_FS_GROUP_FLOW) + dist_type = DPAA2_FLOW_FS_TYPE; + else + dist_type = DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE; - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); + if (dist_type & DPAA2_FLOW_QOS_TYPE) { + ret = dpaa2_flow_get_flow_index(priv, attr, DPAA2_FLOW_QOS_TYPE, NULL); if (ret) return ret; - - (*device_configured) |= local_cfg; - return 0; } + if (dist_type & DPAA2_FLOW_FS_TYPE) + ret = dpaa2_flow_get_flow_index(priv, attr, DPAA2_FLOW_FS_TYPE, NULL); - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_MPLS); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); - return ret; - } + if (!ret && pdist_type) + *pdist_type = dist_type; - if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && - !mask->label_tc_s[2]) - return 0; + return ret; +} - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, - NH_FLD_MPLS_MPLSL_1, spec, - mask, sizeof(*mask), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; +static inline int +dpaa2_flow_verify_patterns(const struct rte_flow_item pattern[], + int sp_support) +{ + unsigned int i, j, is_found = 0; + int ret = 0; + const enum rte_flow_item_type *hp_supported; + const enum rte_flow_item_type *sp_supported; + uint64_t hp_supported_num, sp_supported_num; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, - NH_FLD_MPLS_MPLSL_1, spec, - mask, sizeof(*mask), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; + hp_supported = dpaa2_hp_supported_pattern_type; + hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); + + sp_supported = dpaa2_sp_supported_pattern_type; + sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - (*device_configured) |= local_cfg; + for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { + is_found = 0; + for (i = 0; i < hp_supported_num; i++) { + if (hp_supported[i] == pattern[j].type) { + is_found = 1; + break; + } + } + if (is_found) + continue; + if (sp_support) { + for (i = 0; i < sp_supported_num; i++) { + if (sp_supported[i] == pattern[j].type) { + is_found = 1; + break; + } + } + } + if (!is_found) { + DPAA2_PMD_WARN("Flow type(%d) not supported", + pattern[j].type); + ret = -ENOTSUP; + break; + } + } - return 0; + return ret; } -static int -dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +static inline uint16_t +dpaa2_flow_check_actions_support(const struct rte_flow_action actions[], + const enum rte_flow_action_type supported[], uint16_t len, + struct rte_flow_action actions_get[]) { - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_pppoe *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_pppoe_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_PPPOES); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); - return ret; + uint16_t i, j, num = 0; + + for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) { + for (j = 0; j < len; j++) { + if (supported[j] == actions[i].type) { + if (actions_get) { + actions_get[num].type = actions[i].type; + actions_get[num].conf = actions[i].conf; + } + num++; + } + } } - - if (!mask->session_id) + if (!num) return 0; + if (actions_get) + actions_get[num].type = RTE_FLOW_ACTION_TYPE_END; - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, - NH_FLD_PPPOE_SID, &spec->session_id, - &mask->session_id, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, - NH_FLD_PPPOE_SID, &spec->session_id, - &mask->session_id, sizeof(rte_be16_t), - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - - return 0; + return num; } static int -dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) +dpaa2_flow_validate(struct rte_eth_dev *dev, + const struct rte_flow_attr *flow_attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - int local_cfg = 0, ret; - uint32_t group; - struct dpaa2_key_extract *qos_key_extract; - struct dpaa2_key_extract *tc_key_extract; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - const struct rte_flow_item_raw *spec = pattern->spec; - const struct rte_flow_item_raw *mask = pattern->mask; - - /* Need both spec and mask */ - if (!spec || !mask) { - DPAA2_PMD_ERR("spec or mask not present."); - return -EINVAL; - } - - if (spec->relative) { - /* TBD: relative offset support. - * To support relative offset of previous L3 protocol item, - * extracts should be expanded to identify if the frame is: - * vlan or none-vlan. - * - * To support relative offset of previous L4 protocol item, - * extracts should be expanded to identify if the frame is: - * vlan/IPv4 or vlan/IPv6 or none-vlan/IPv4 or none-vlan/IPv6. - */ - DPAA2_PMD_ERR("relative not supported."); - return -EINVAL; + struct rte_flow_attr attr; + uint16_t action_num; + int ret = 0; + enum rte_flow_action_type supported; + const char *err_str = NULL; + const void *cause = NULL; + enum dpaa2_flow_dist_type dist_type = DPAA2_FLOW_NULL_TYPE; + enum rte_flow_error_type err_type = RTE_FLOW_ERROR_TYPE_NONE; + + if (!flow_attr) { + err_str = "No attribute specifiec."; + cause = flow_attr; + err_type = RTE_FLOW_ERROR_TYPE_ATTR; + ret = -EPERM; + goto invalid_params; + } + if (!actions) { + err_str = "No action specifiec."; + cause = flow_attr; + err_type = RTE_FLOW_ERROR_TYPE_ACTION; + ret = -EPERM; + goto invalid_params; + } + + ret = dpaa2_flow_attr_group_convert(priv, flow_attr, &attr); + if (ret) { + err_str = "Failure to convert attribute!"; + cause = flow_attr; + err_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP; + goto invalid_params; } - if (spec->search) { - DPAA2_PMD_ERR("search not supported."); - return -EINVAL; + supported = RTE_FLOW_ACTION_TYPE_RSS; + action_num = dpaa2_flow_check_actions_support(actions, &supported, 1, NULL); + if (action_num) { + DPAA2_PMD_DEBUG("This is rss flow."); + goto rss_check; } + goto verify_attr; - /* Spec len and mask len should be same */ - if (spec->length != mask->length) { - DPAA2_PMD_ERR("Spec len and mask len mismatch."); - return -EINVAL; +rss_check: + if (action_num > 1) { + err_str = "Multiple flow's action."; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION_NUM; + ret = -EPERM; + goto invalid_params; } - /* Get traffic class index and flow id to be configured */ - group = attr->group; - flow->tc_id = group; - flow->tc_index = attr->priority; - - qos_key_extract = &priv->extract.qos_key_extract; - tc_key_extract = &priv->extract.tc_key_extract[group]; - - ret = dpaa2_flow_extract_add_raw(priv, - spec->offset, spec->length, - DPAA2_FLOW_QOS_TYPE, 0, &local_cfg); +verify_attr: + /* Verify input attributes */ + ret = dpaa2_flow_verify_steering_attr(priv, &attr, &dist_type); if (ret) { - DPAA2_PMD_ERR("QoS Extract RAW add failed."); - return -EINVAL; + err_str = "Invalid attributes are given"; + cause = flow_attr; + err_type = RTE_FLOW_ERROR_TYPE_ATTR; + goto invalid_params; } - ret = dpaa2_flow_extract_add_raw(priv, - spec->offset, spec->length, - DPAA2_FLOW_FS_TYPE, group, &local_cfg); - if (ret) { - DPAA2_PMD_ERR("FS[%d] Extract RAW add failed.", - group); - return -EINVAL; + if (pattern) { + /* Verify input pattern list */ + ret = dpaa2_flow_verify_patterns(pattern, priv->sp_protocol); + if (ret) { + err_str = "Invalid pattern list is given"; + cause = pattern; + err_type = RTE_FLOW_ERROR_TYPE_ITEM; + goto invalid_params; + } } - ret = dpaa2_flow_raw_rule_data_set(flow, - &qos_key_extract->key_profile, - spec->offset, spec->length, - spec->pattern, mask->pattern, - DPAA2_FLOW_QOS_TYPE); - if (ret) { - DPAA2_PMD_ERR("QoS RAW rule data set failed"); - return -EINVAL; + /* Verify input action list */ + if (dist_type & DPAA2_FLOW_FS_TYPE) { + if (!dpaa2_flow_check_actions_support(actions, + dpaa2_supported_fs_action_type, + RTE_DIM(dpaa2_supported_fs_action_type), NULL)) { + err_str = "Invalid FS action list is given"; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION; + ret = -ENOTSUP; + goto invalid_params; + } } - - ret = dpaa2_flow_raw_rule_data_set(flow, - &tc_key_extract->key_profile, - spec->offset, spec->length, - spec->pattern, mask->pattern, - DPAA2_FLOW_FS_TYPE); - if (ret) { - DPAA2_PMD_ERR("FS RAW rule data set failed"); - return -EINVAL; + if (dist_type & DPAA2_FLOW_QOS_TYPE) { + if (!dpaa2_flow_check_actions_support(actions, + dpaa2_supported_qos_action_type, + RTE_DIM(dpaa2_supported_qos_action_type), NULL)) { + err_str = "Invalid QoS action list is given"; + cause = actions; + err_type = RTE_FLOW_ERROR_TYPE_ACTION; + ret = -ENOTSUP; + goto invalid_params; + } } - (*device_configured) |= local_cfg; +invalid_params: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(error, -ret, err_type, cause, err_str); - return 0; + return ret; } -static inline int -dpaa2_flow_verify_attr(struct dpaa2_dev_priv *priv, - const struct rte_flow_attr *attr) +static uint32_t +dpaa2_flow_is_ip_addr_extract(const struct dpkg_extract *extract) { - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); + enum dpkg_extract_type type = extract->type; + enum net_prot prot = extract->extract.from_hdr.prot; + uint32_t field = extract->extract.from_hdr.field; - while (curr) { - if (curr->tc_id == attr->group && - curr->tc_index == attr->priority) { - DPAA2_PMD_ERR("Flow(TC[%d].entry[%d] exists", - attr->group, attr->priority); - - return -EINVAL; - } - curr = LIST_NEXT(curr, next); - } + if (type == DPKG_EXTRACT_FROM_HDR && prot == NET_PROT_IP && + (field == NH_FLD_IP_SRC || field == NH_FLD_IP_DST)) + return field; return 0; } -static inline struct rte_eth_dev * -dpaa2_flow_redirect_dev(struct dpaa2_dev_priv *priv, - const struct rte_flow_action *action) +static void +dpaa2_flow_key_offset_size(struct dpaa2_key_profile *key_profile, + uint8_t idx, uint8_t *offset, uint8_t *size) { - const struct rte_flow_action_port_id *port_id; - const struct rte_flow_action_ethdev *ethdev; - int idx = -1; - struct rte_eth_dev *dest_dev; - - if (action->type == RTE_FLOW_ACTION_TYPE_PORT_ID) { - port_id = action->conf; - if (!port_id->original) - idx = port_id->id; - } else if (action->type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { - ethdev = action->conf; - idx = ethdev->port_id; - } else { - return NULL; - } - - if (idx >= 0) { - if (!rte_eth_dev_is_valid_port(idx)) - return NULL; - if (!rte_pmd_dpaa2_dev_is_dpaa2(idx)) - return NULL; - dest_dev = &rte_eth_devices[idx]; + uint8_t ip_addr_size = 0; + + if (key_profile->ip_addr[0].field && + key_profile->ip_addr[0].extract_idx == idx) { + ip_addr_size = key_profile->ip_addr[0].max_size; + *offset = key_profile->ip_addr_offset; + *size = ip_addr_size; + } else if (key_profile->ip_addr[1].field && + key_profile->ip_addr[1].extract_idx == idx) { + ip_addr_size = key_profile->ip_addr[1].max_size; + *offset = key_profile->ip_addr_offset + ip_addr_size; + *size = ip_addr_size; } else { - dest_dev = priv->eth_dev; + *offset = key_profile->prot_field[idx].key_offset; + *size = key_profile->prot_field[idx].key_size; } - - return dest_dev; } -static inline int -dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, - const struct rte_flow_attr *attr, - const struct rte_flow_action actions[]) +static int +dpaa2_flow_rule_data_valid(struct dpaa2_generic_flow *flow, + uint8_t key_offset, uint8_t key_size) { - int end_of_list = 0, i, j = 0; - const struct rte_flow_action_queue *dest_queue; - const struct rte_flow_action_rss *rss_conf; - struct dpaa2_queue *rxq; - - while (!end_of_list) { - switch (actions[j].type) { - case RTE_FLOW_ACTION_TYPE_QUEUE: - dest_queue = actions[j].conf; - if (dest_queue->index >= MAX_RX_QUEUES || - !priv->rx_vq[dest_queue->index]) { - DPAA2_PMD_ERR("Invalid FSQ index(%d)", - dest_queue->index); - - return -EINVAL; - } - rxq = priv->rx_vq[dest_queue->index]; - if (attr->group != rxq->tc_index) { - DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", - rxq->tc_index, rxq->flow_id, - attr->group); + uint8_t i; + int valid = false; - return -ENOTSUP; - } - break; - case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: - case RTE_FLOW_ACTION_TYPE_PORT_ID: - if (!dpaa2_flow_redirect_dev(priv, &actions[j])) { - DPAA2_PMD_ERR("Invalid port id of action"); - return -ENOTSUP; - } - break; - case RTE_FLOW_ACTION_TYPE_RSS: - rss_conf = (const struct rte_flow_action_rss *) - (actions[j].conf); - if (rss_conf->queue_num > priv->dist_queues) { - DPAA2_PMD_ERR("RSS number too large"); - return -ENOTSUP; - } - for (i = 0; i < (int)rss_conf->queue_num; i++) { - if (rss_conf->queue[i] >= priv->nb_rx_queues) { - DPAA2_PMD_ERR("RSS queue not in range"); - return -ENOTSUP; - } - rxq = priv->rx_vq[rss_conf->queue[i]]; - if (rxq->tc_index != attr->group) { - DPAA2_PMD_ERR("RSS queue not in group"); - return -ENOTSUP; - } - } + if (!flow->mask_addr) + return valid; + for (i = 0; i < key_size; i++) { + if (flow->mask_addr[key_offset + i]) { + valid = true; break; - case RTE_FLOW_ACTION_TYPE_PF: - /* Skip this action, have to add for vxlan */ - case RTE_FLOW_ACTION_TYPE_DROP: - break; - case RTE_FLOW_ACTION_TYPE_END: - end_of_list = 1; - break; - default: - DPAA2_PMD_ERR("Invalid action type"); - return -ENOTSUP; } - j++; } - return 0; + return valid; } -static int -dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, - struct dpaa2_dev_flow *flow, - const struct rte_flow_action *rte_action) +static void +dpaa2_flow_remove_invalid_rule_data(struct dpaa2_dev_priv *priv, + enum dpaa2_flow_dist_type type, uint8_t tc_id, + uint8_t key_offset, uint8_t key_size) { - struct rte_eth_dev *dest_dev; - struct dpaa2_dev_priv *dest_priv; - const struct rte_flow_action_queue *dest_queue; - struct dpaa2_queue *dest_q; - uint64_t flc = 0; - - memset(&flow->fs_action_cfg, 0, - sizeof(struct dpni_fs_action_cfg)); - flow->action_type = rte_action->type; + struct dpaa2_dev_flow *dev_flow, *next_flow; + struct dpaa2_generic_flow *flow; + uint8_t *src, *dst, size; + + dev_flow = LIST_FIRST(&priv->flows); + while (dev_flow) { + next_flow = LIST_NEXT(dev_flow, next); + flow = dpaa2_flow_generic_flow(dev_flow, type, tc_id); + if (!flow || !flow->key_addr || !flow->mask_addr) + goto skip_update; + + if (key_offset < flow->rule_size) { + src = flow->key_addr + key_offset + key_size; + dst = src - key_size; + size = flow->rule_size - (key_offset + key_size); + memmove(dst, src, size); + + src = flow->mask_addr + key_offset + key_size; + dst = src - key_size; + memmove(dst, src, size); + flow->rule_size -= key_size; + } + if (flow->rule_cfg.key_size > flow->rule_size) { + memset(flow->key_addr + flow->rule_size, 0, + flow->rule_cfg.key_size - flow->rule_size); + memset(flow->mask_addr + flow->rule_size, 0, + flow->rule_cfg.key_size - flow->rule_size); + } - if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { - dest_queue = rte_action->conf; - if (dest_queue->index >= MAX_RX_QUEUES || - !priv->rx_vq[dest_queue->index]) { - DPAA2_PMD_ERR("Invalid FSQ index(%d)", - dest_queue->index); +skip_update: + dev_flow = next_flow; + } +} - return -EINVAL; +static int +dpaa2_flow_remove_invalid_extract(struct rte_eth_dev *dev, + enum dpaa2_flow_dist_type type, uint8_t tc_id) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *dev_flow, *next_flow; + uint8_t i, key_offset, key_size, j, remove_conut = 0; + struct dpaa2_key_profile *key_profile; + struct dpaa2_ip_addr_extract *ip_addr; + struct dpaa2_l4_port_extract *l4_port; + int valid[DPKG_MAX_NUM_OF_EXTRACTS], update = 0, l4_idx; + uint32_t start, end, size; + uint32_t ip_src_size, ip_dst_size, ip_addr_size = 0, is_ip; + struct dpaa2_generic_flow *flow; + void *src, *dst; + + key_profile = type == DPAA2_FLOW_QOS_TYPE ? + &priv->flow_profile.qos_profile.key_profile : + &priv->flow_profile.tc_profile[tc_id].key_profile; + + ip_addr = key_profile->ip_addr; + l4_port = key_profile->l4_port; + ip_addr_size = dpaa2_extract_ip_addr_size(ip_addr); + for (i = 0; i < key_profile->dpkg.num_extracts; i++) { + valid[i] = 0; + dev_flow = LIST_FIRST(&priv->flows); + dpaa2_flow_key_offset_size(key_profile, i, &key_offset, &key_size); + while (dev_flow) { + next_flow = LIST_NEXT(dev_flow, next); + flow = dpaa2_flow_generic_flow(dev_flow, type, tc_id); + if (!flow) + goto skip_validation; + + if (dpaa2_flow_rule_data_valid(flow, key_offset, key_size)) { + valid[i] = 1; + break; + } +skip_validation: + dev_flow = next_flow; } - dest_q = priv->rx_vq[dest_queue->index]; - if (flow->tc_id != dest_q->tc_index) { - DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", - dest_queue->index, - dest_q->tc_index, dest_q->flow_id, - flow->tc_id); + if (!valid[i]) + remove_conut++; + } - return -EINVAL; - } - flow->fs_action_cfg.options = - DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + if (remove_conut > 0) { + if (type == DPAA2_FLOW_QOS_TYPE) + dpaa2_flow_extracts_log(priv, "Before removing extract(s)", MAX_TCS); + else + dpaa2_flow_extracts_log(priv, "Before removing extract(s)", tc_id); + } else { + return 0; + } - if (dest_q->data_stashing_off) { - dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, - 0, &flc); - } else { - dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, - 1, &flc); + i = key_profile->dpkg.num_extracts - 1; + while (remove_conut) { + if (valid[i]) { + if (i == 0) { + DPAA2_PMD_ERR("Fatal: %d key(s) not removed!", remove_conut); + return -EINVAL; + } + i--; + continue; } - if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { - dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, - 1, &flc); + is_ip = false; + for (j = 0; j < 2; j++) { + if (key_profile->prot_field[i].type == DPAA2_NET_PROT_KEY && + key_profile->prot_field[i].prot == NET_PROT_IP && + key_profile->prot_field[i].key_field == + key_profile->ip_addr[j].field) { + key_size = key_profile->ip_addr[j].max_size; + key_offset = key_profile->ip_addr_offset + j * key_size; + is_ip = true; + break; + } } - - flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; - flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; - flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; - flow->fs_action_cfg.flc = flc; - flow->fs_action_cfg.flow_id = dest_q->flow_id; - } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || - flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { - dest_dev = dpaa2_flow_redirect_dev(priv, rte_action); - if (!dest_dev) { - DPAA2_PMD_ERR("Invalid device to redirect"); - return -EINVAL; + if (!is_ip) { + key_size = key_profile->prot_field[i].key_size; + key_offset = key_profile->prot_field[i].key_offset; } - dest_priv = dest_dev->data->dev_private; - dest_q = dest_priv->tx_vq[0]; - flow->fs_action_cfg.options = - DPNI_FS_OPT_REDIRECT_TO_DPNI_TX; - flow->fs_action_cfg.num_tokens = 1; - flow->fs_action_cfg.redir_tokens[0] = dest_priv->token; - flow->fs_action_cfg.flow_id = dest_q->flow_id; - } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { - flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; - } + for (j = i + 1; j < key_profile->dpkg.num_extracts; j++) + key_profile->prot_field[j].key_offset -= key_size; - return 0; -} + if (!dpaa2_flow_is_ip_addr_extract(&key_profile->dpkg.extracts[i])) + update += key_size; -static inline uint16_t -dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) -{ - if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { - DPAA2_PMD_ERR("Key size(%d) > max(%d)", - key_max_size, - DPAA2_FLOW_ENTRY_MAX_SIZE); + if ((i + 1) < key_profile->dpkg.num_extracts) { + src = &key_profile->prot_field[i + 1]; + dst = &key_profile->prot_field[i]; + size = (key_profile->dpkg.num_extracts - i - 1) * + sizeof(struct key_prot_field); + memmove(dst, src, size); - return 0; - } + src = &key_profile->dpkg.extracts[i + 1]; + dst = &key_profile->dpkg.extracts[i]; + size = (key_profile->dpkg.num_extracts - i - 1) * + sizeof(struct dpkg_extract); + memmove(dst, src, size); + } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || - dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) - return DPAA2_FLOW_ENTRY_MAX_SIZE; + dpaa2_flow_remove_invalid_rule_data(priv, type, tc_id, key_offset, key_size); - return DPAA2_FLOW_ENTRY_MIN_SIZE; -} + key_profile->dpkg.num_extracts--; + i--; + remove_conut--; + }; -static inline int -dpaa2_flow_clear_fs_table(struct dpaa2_dev_priv *priv, - uint8_t tc_id) -{ - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - int need_clear = 0, ret; - struct fsl_mc_io *dpni = priv->hw; + key_profile->key_max_size -= update; + key_profile->key_max_size -= ip_addr_size; - while (curr) { - if (curr->tc_id == tc_id) { - need_clear = 1; - break; + memset(ip_addr, 0, sizeof(struct dpaa2_ip_addr_extract) * 2); + memset(l4_port, 0, sizeof(struct dpaa2_l4_port_extract) * DPAA2_L4_PORT_NUM); + + if (key_profile->dpkg.num_extracts >= 2) + start = key_profile->dpkg.num_extracts - 2; + else if (key_profile->dpkg.num_extracts >= 1) + start = key_profile->dpkg.num_extracts - 1; + else + goto skip_ip_addr_extract; + end = key_profile->dpkg.num_extracts; + + j = 0; + for (i = start; i < end; i++) { + if (dpaa2_flow_is_ip_addr_extract(&key_profile->dpkg.extracts[i])) { + ip_addr[j].field = key_profile->dpkg.extracts[i].extract.from_hdr.field; + ip_addr[j].max_size = sizeof(rte_be32_t); + ip_addr[j].extract_idx = i; + j++; } - curr = LIST_NEXT(curr, next); } - if (need_clear) { - ret = dpni_clear_fs_entries(dpni, CMD_PRI_LOW, - priv->token, tc_id); - if (ret) { - DPAA2_PMD_ERR("TC[%d] clear failed", tc_id); - return ret; + ip_src_size = sizeof(rte_be32_t); + ip_dst_size = sizeof(rte_be32_t); + dev_flow = LIST_FIRST(&priv->flows); + while (dev_flow) { + next_flow = LIST_NEXT(dev_flow, next); + flow = dpaa2_flow_generic_flow(dev_flow, type, tc_id); + if (!flow) + goto skip_ip_addr_size_update; + + if (flow->ip_key == NET_PROT_IPV6) { + if (flow->ip_src == NET_PROT_IPV6) + ip_src_size = NH_FLD_IPV6_ADDR_SIZE; + if (flow->ip_dst == NET_PROT_IPV6) + ip_dst_size = NH_FLD_IPV6_ADDR_SIZE; + } + +skip_ip_addr_size_update: + dev_flow = next_flow; + } + for (i = 0; i < 2; i++) { + if (ip_addr[i].field == NH_FLD_IP_SRC) { + ip_addr[i].max_size = ip_src_size; + key_profile->key_max_size += ip_src_size; + } else if (ip_addr[i].field == NH_FLD_IP_DST) { + ip_addr[i].max_size = ip_dst_size; + key_profile->key_max_size += ip_dst_size; + } + } + +skip_ip_addr_extract: + for (i = 0; i < key_profile->dpkg.num_extracts; i++) { + l4_idx = dpaa2_flow_l4_port_extract(&key_profile->dpkg.extracts[i]); + if (l4_idx < 0) + continue; + if (key_profile->l4_port[l4_idx].present) { + DPAA2_PMD_WARN("Multiple L4 port[%d] extracts:%d/%d", + l4_idx, key_profile->l4_port[l4_idx].extract_idx, i); } + key_profile->l4_port[l4_idx].present = true; + key_profile->l4_port[l4_idx].extract_idx = i; + key_profile->l4_port[l4_idx].key_offset = key_profile->prot_field[i].key_offset; } - return 0; + if (type == DPAA2_FLOW_QOS_TYPE) + dpaa2_flow_extracts_log(priv, "After removing extract(s)", MAX_TCS); + else + dpaa2_flow_extracts_log(priv, "After removing extract(s)", tc_id); + + return update; } static int -dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, - uint8_t tc_id, uint16_t dist_size, int rss_dist) +dpaa2_flow_remove_steering_entry(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, enum dpaa2_flow_dist_type type) { - struct dpaa2_key_extract *tc_extract; - uint8_t *key_cfg_buf; - uint64_t key_cfg_iova; - int ret; - struct dpni_rx_dist_cfg tc_cfg; + int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; struct fsl_mc_io *dpni = priv->hw; - uint16_t entry_size; - uint16_t key_max_size; + struct dpaa2_flow_tbl_profile *tbl_profile; - ret = dpaa2_flow_clear_fs_table(priv, tc_id); - if (ret < 0) { - DPAA2_PMD_ERR("TC[%d] clear failed", tc_id); - return ret; + if (!dpaa2_flow_is_steering_flow(flow)) { + DPAA2_PMD_ERR("%s: flow(type=%x) is not steering flow", + __func__, flow->type); + return -EINVAL; } - tc_extract = &priv->extract.tc_key_extract[tc_id]; - key_cfg_buf = priv->extract.tc_extract_param[tc_id]; - key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf, - DPAA2_EXTRACT_PARAM_MAX_SIZE); - if (key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, key_cfg_buf); - - return -ENOBUFS; + if (type == DPAA2_FLOW_QOS_TYPE) { + tbl_profile = &priv->flow_profile.qos_profile; + ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, + priv->token, &flow->rule_cfg); + } else { + tbl_profile = &priv->flow_profile.tc_profile[flow->tc_id]; + ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, + priv->token, flow->tc_id, &flow->rule_cfg); + } + dpaa2_flow_steering_entry_log(ret ? "Remove failure" : "Remove success", flow); + if (!ret) { + tbl_profile->entry_num--; + dpaa2_flow_entry_map_set(tbl_profile->entry_map, flow->entry_index, 0); } - key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(priv, key_max_size); + return ret; +} - dpaa2_flow_fs_extracts_log(priv, tc_id); - ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, - key_cfg_buf); +static int +dpaa2_flow_rss_action_update(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile = NULL; + int ret = 0, err_code = 0, i = 0; + const struct rte_flow_action_rss *rss_conf; + struct rte_flow_item items[DPKG_MAX_NUM_OF_EXTRACTS + 1]; + uint8_t spec_buf[1024], tc_id; + struct rte_flow_attr attr; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + uint64_t rss_dist; + + tc_id = flow->tc_id; + tbl_profile = &priv->flow_profile.tc_profile[tc_id]; + rss_conf = actions[0].conf; + if (pattern) { + while (i < (DPKG_MAX_NUM_OF_EXTRACTS + 1)) { + rte_memcpy(&items[i], &pattern[i], sizeof(struct rte_flow_item)); + if (pattern[i].type == RTE_FLOW_ITEM_TYPE_END) + break; + i++; + } + if (items[i - 1].type != RTE_FLOW_ITEM_TYPE_END) { + error_type = RTE_FLOW_ERROR_TYPE_ITEM_NUM; + err_str = "Too many patterns for RSS"; + err_code = -EINVAL; + goto quit; + } + goto set_extract; + } + rss_dist = rss_conf->types; + ret = dpaa2_flow_rss_conf_to_item(rss_dist, items, spec_buf, 1024); if (ret < 0) { - DPAA2_PMD_ERR("TC[%d] prepare key failed", tc_id); - return ret; + DPAA2_PMD_ERR("Failed(%d) to convert TC.%d's rss distribution", ret, tc_id); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to gen rss items in flow action update!"; + err_code = ret; + goto quit; + } else if (!ret) { + DPAA2_PMD_ERR("No item is generated by rss dist(0x%lx)", rss_dist); + error_type = RTE_FLOW_ERROR_TYPE_ITEM; + err_str = "No item is generated by rss type!"; + err_code = -ENOTSUP; + goto quit; + } + +set_extract: + memset(&attr, 0, sizeof(attr)); + attr.group = tc_id; + attr.ingress = 1; + tbl_profile->tc_cfg.dist_size = rss_conf->queue_num; + flow->rule_size = 0; + flow->ip_key = NET_PROT_NONE; + flow->ip_src = NET_PROT_NONE; + flow->ip_dst = NET_PROT_NONE; + ret = dpaa2_flow_generic_extract_rule_set(flow, items, NULL); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "RSS extracts update failed!"; + err_code = ret; + goto quit; + } + ret = dpaa2_flow_table_update(priv, DPAA2_FLOW_RSS_TYPE, attr.group, true); + if (ret) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "RSS table update failed!"; + err_code = ret; } - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - tc_cfg.dist_size = dist_size; - tc_cfg.key_cfg_iova = key_cfg_iova; - if (rss_dist) - tc_cfg.enable = true; - else - tc_cfg.enable = false; - tc_cfg.tc = tc_id; - ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, - priv->token, &tc_cfg); - if (ret < 0) { - if (rss_dist) { - DPAA2_PMD_ERR("RSS TC[%d] set failed", - tc_id); - } else { - DPAA2_PMD_ERR("FS TC[%d] hash disable failed", - tc_id); - } +quit: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + return rte_flow_error_set(error, -err_code, error_type, NULL, err_str); +} - return ret; - } +static int +dpaa2_flow_destroy_steering_flow(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow) +{ + int ret = 0, update; + uint8_t tc_id = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; - if (rss_dist) + if (!flow) return 0; - uint16_t nb_rxq = priv->eth_dev->data->nb_rx_queues; - uint16_t first = tc_id * dist_size; - - tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = nb_rxq > first ? - RTE_MIN(dist_size, nb_rxq - first) - 1 : 0; - ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, - priv->token, &tc_cfg); - if (ret < 0) { - DPAA2_PMD_ERR("TC[%d] FS configured failed", tc_id); - return ret; + if (!dpaa2_flow_is_steering_flow(flow)) { + DPAA2_PMD_ERR("%s: flow(type=%x) is not steering flow", + __func__, flow->type); + return -EINVAL; } - ret = dpaa2_flow_rule_add_all(priv, DPAA2_FLOW_FS_TYPE, - entry_size, tc_id); + dpaa2_dump_extract_map(priv, "Start destroying flow", flow->type, + flow->type == DPAA2_FLOW_FS_TYPE ? flow->tc_id : 0); + + ret = dpaa2_flow_remove_steering_entry(dev, flow, flow->type); if (ret) return ret; - return 0; + update = dpaa2_flow_remove_invalid_extract(dev, flow->type, flow->tc_id); + if (update > 0) + ret = dpaa2_flow_table_update(priv, flow->type, flow->tc_id, false); + + if (!ret) { + dpaa2_dump_extract_map(priv, "End destroying flow", flow->type, tc_id); + dpaa2_flow_generic_flow_deinit(flow); + } + + return ret; } static int -dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, - int rss_dist) +dpaa2_flow_destroy_rss_flow(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow) { - struct dpaa2_key_extract *qos_extract; - uint8_t *key_cfg_buf; - uint64_t key_cfg_iova; - int ret; - struct dpni_qos_tbl_cfg qos_cfg; - struct fsl_mc_io *dpni = priv->hw; - uint16_t entry_size; - uint16_t key_max_size; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int update, ret; - if (!rss_dist && priv->num_rx_tc <= 1) { - /* QoS table is effecitive for FS multiple TCs or RSS.*/ + if (!flow) return 0; - } - if (LIST_FIRST(&priv->flows)) { - ret = dpni_clear_qos_table(dpni, CMD_PRI_LOW, - priv->token); - if (ret < 0) { - DPAA2_PMD_ERR("QoS table clear failed"); - return ret; + update = dpaa2_flow_remove_invalid_extract(dev, flow->type, flow->tc_id); + if (update > 0) { + ret = dpaa2_flow_table_update(priv, flow->type, flow->tc_id, true); + } else { + if (!update) { + DPAA2_PMD_ERR("No TC.%d's RSS flow was found", flow->tc_id); + ret = -EINVAL; + } else { + ret = update; } } - qos_extract = &priv->extract.qos_key_extract; - key_cfg_buf = priv->extract.qos_extract_param; - key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(key_cfg_buf, - DPAA2_EXTRACT_PARAM_MAX_SIZE); - if (key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, key_cfg_buf); - - return -ENOBUFS; + if (!ret) { + priv->flow_profile.tc_profile[flow->tc_id].rss_flow = NULL; + dpaa2_flow_generic_flow_deinit(flow); } - key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(priv, key_max_size); + return ret; +} - dpaa2_flow_qos_extracts_log(priv); +static struct dpaa2_generic_flow * +dpaa2_flow_create_steering_flow(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error, + enum dpaa2_flow_dist_type dist_type) +{ + struct dpaa2_generic_flow *flow = NULL; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret, extract_cfg = 0; + uint16_t idx; - ret = dpkg_prepare_key_cfg(&qos_extract->dpkg, - key_cfg_buf); - if (ret < 0) { - DPAA2_PMD_ERR("QoS prepare extract failed"); - return ret; - } - memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg)); - qos_cfg.keep_entries = true; - qos_cfg.key_cfg_iova = key_cfg_iova; - if (rss_dist) { - qos_cfg.discard_on_miss = true; - } else { - qos_cfg.discard_on_miss = false; - qos_cfg.default_tc = 0; - } + ret = dpaa2_flow_get_flow_index(priv, attr, dist_type, &idx); + if (ret) + return NULL; - if (priv->mc_rev < DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV) - ret = dpni_set_qos_table_v2(dpni, CMD_PRI_LOW, - priv->token, &qos_cfg); - else - ret = dpni_set_qos_table(dpni, CMD_PRI_LOW, - priv->token, &qos_cfg); - if (ret < 0) { - DPAA2_PMD_ERR("QoS table set failed"); - return ret; - } + ret = dpaa2_flow_verify_flow_action(priv, attr, actions); + if (ret) + return NULL; - ret = dpaa2_flow_rule_add_all(priv, DPAA2_FLOW_QOS_TYPE, - entry_size, 0); + ret = dpaa2_flow_verify_steering_entry(priv, attr->group, idx, dist_type); if (ret) - return ret; + return NULL; - return 0; -} + dpaa2_dump_extract_map(priv, "Start creating flow", dist_type, attr->group); -static int -dpaa2_flow_item_convert(const struct rte_flow_item pattern[], - struct rte_dpaa2_flow_item **dpaa2_pattern, int sp_protocol) -{ - struct rte_dpaa2_flow_item *new_pattern; - int num = 0, tunnel_start = 0; + flow = dpaa2_flow_generic_flow_init(priv, idx, false, dist_type, attr->group); + if (!flow) + return NULL; - while (1) { - num++; - if (pattern[num].type == RTE_FLOW_ITEM_TYPE_END) - break; - } + if (dist_type == DPAA2_FLOW_FS_TYPE) + dpaa2_flow_clean(dev, flow->tc_id, DPAA2_FLOW_RSS_TYPE); - new_pattern = rte_malloc(NULL, sizeof(struct rte_dpaa2_flow_item) * num, - RTE_CACHE_LINE_SIZE); - if (!new_pattern) { - DPAA2_PMD_ERR("Failed to alloc %d flow items", num); - return -ENOMEM; + ret = dpaa2_flow_generic_extract_rule_set(flow, pattern, &extract_cfg); + if (ret < 0) { + if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) { + rte_flow_error_set(error, EPERM, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + attr, "unknown"); + } + DPAA2_PMD_ERR("Failed(%d) to create FS flow.", ret); + goto creation_error; + } + if (extract_cfg) { + ret = dpaa2_flow_table_update(priv, dist_type, attr->group, false); + if (ret) + goto creation_error; } - num = 0; - while (pattern[num].type != RTE_FLOW_ITEM_TYPE_END) { - rte_memcpy(&new_pattern[num].generic_item, &pattern[num], - sizeof(struct rte_flow_item)); - new_pattern[num].in_tunnel = 0; + ret = dpaa2_flow_steering_action_convert(flow, actions); + if (ret) + goto creation_error; - if (pattern[num].type == RTE_FLOW_ITEM_TYPE_VXLAN) - tunnel_start = 1; - else if (tunnel_start && sp_protocol) - new_pattern[num].in_tunnel = 1; - num++; - } + ret = dpaa2_flow_add_steering_rule(flow, false); + if (ret) + goto creation_error; - new_pattern[num].generic_item.type = RTE_FLOW_ITEM_TYPE_END; - *dpaa2_pattern = new_pattern; + dpaa2_dump_extract_map(priv, "Complete creating flow", dist_type, attr->group); - return 0; + return flow; + +creation_error: + dpaa2_flow_generic_flow_deinit(flow); + + return NULL; } -static int -dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, +static struct dpaa2_generic_flow * +dpaa2_flow_create_rss_flow(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, const struct rte_flow_item pattern[], const struct rte_flow_action actions[], struct rte_flow_error *error) { - const struct rte_flow_action_rss *rss_conf; - int is_keycfg_configured = 0, end_of_list = 0; - int ret = 0, i = 0, j = 0; + struct dpaa2_generic_flow *flow = NULL; struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); - uint16_t dist_size, key_size; - struct dpaa2_key_extract *qos_key_extract; - struct dpaa2_key_extract *tc_key_extract; - struct rte_dpaa2_flow_item *dpaa2_pattern = NULL; + int ret, tc = RTE_DPAA2_FLOW_GROUP_ID_GET(attr->group); - ret = dpaa2_flow_verify_attr(priv, attr); - if (ret) - return ret; + if (tc >= priv->num_rx_tc) { + DPAA2_PMD_ERR("Flow group(%d) >= max(%d)", + attr->group, priv->num_rx_tc); + return NULL; + } - ret = dpaa2_flow_verify_action(priv, attr, actions); + ret = dpaa2_flow_verify_flow_action(priv, attr, actions); if (ret) - return ret; + return NULL; + + dpaa2_flow_clean(dev, tc, DPAA2_FLOW_FS_TYPE); - ret = dpaa2_flow_item_convert(pattern, &dpaa2_pattern, - priv->sp_protocol); + flow = dpaa2_flow_generic_flow_init(priv, 0, true, + DPAA2_FLOW_RSS_TYPE, tc); + if (!flow) + return NULL; + ret = dpaa2_flow_rss_action_update(dev, flow, pattern, actions, error); if (ret) - return ret; + goto creation_error; - /* Parse pattern list to get the matching parameters */ - while (!end_of_list) { - switch (pattern[i].type) { - case RTE_FLOW_ITEM_TYPE_ETH: - ret = dpaa2_configure_flow_eth(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ETH flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_VLAN: - ret = dpaa2_configure_flow_vlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("vLan flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_IPV4: - ret = dpaa2_configure_flow_ipv4(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("IPV4 flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_IPV6: - ret = dpaa2_configure_flow_ipv6(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("IPV6 flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ICMP: - ret = dpaa2_configure_flow_icmp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ICMP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_UDP: - ret = dpaa2_configure_flow_udp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("UDP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_TCP: - ret = dpaa2_configure_flow_tcp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("TCP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_SCTP: - ret = dpaa2_configure_flow_sctp(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("SCTP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ESP: - ret = dpaa2_configure_flow_esp(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ESP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_AH: - ret = dpaa2_configure_flow_ah(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("AH flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_GRE: - ret = dpaa2_configure_flow_gre(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("GRE flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_GTP: - ret = dpaa2_configure_flow_gtp(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("GTP flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_MPLS: - ret = dpaa2_configure_flow_mpls(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("MPLS flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_PPPOES: - ret = dpaa2_configure_flow_pppoe(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("PPPoE flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_RAW: - ret = dpaa2_configure_flow_raw(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("RAW flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_END: - end_of_list = 1; - break; /*End of List*/ - default: - DPAA2_PMD_ERR("Invalid flow item[%d] type(%d)", - i, pattern[i].type); - ret = -ENOTSUP; - break; + priv->flow_profile.tc_profile[tc].rss_flow = flow; + + return flow; + +creation_error: + dpaa2_flow_generic_flow_deinit(flow); + + return NULL; +} + +static struct rte_flow * +dpaa2_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *pattr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct dpaa2_dev_flow *flow = NULL, *curr; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct rte_flow_attr attr; + struct rte_flow_action jump_actions[2]; + struct rte_flow_action_jump jump_tc; + const struct rte_flow_action *qos_actions; + uint8_t fs_action_idx = 0; + int ret, err_code = 0; + struct dpaa2_generic_flow *rss_flow = NULL; + struct dpaa2_generic_flow *qos_flow = NULL; + struct dpaa2_generic_flow *fs_flow = NULL; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + + ret = dpaa2_flow_attr_group_convert(priv, pattr, &attr); + if (ret) { + err_str = "Failure to convert attribute!"; + error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP; + err_code = ret; + goto flow_failure; + } + + flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), + RTE_CACHE_LINE_SIZE); + if (!flow) { + err_str = "Failure to allocate memory for flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -ENOMEM; + goto flow_failure; + } + if (actions && actions[0].type == RTE_FLOW_ACTION_TYPE_RSS) { + rss_flow = dpaa2_flow_create_rss_flow(dev, &attr, pattern, actions, error); + if (!rss_flow) { + err_str = "Failure to create RSS flow!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; } - i++; + flow->rss_flow = rss_flow; + goto insert_flow; } - qos_key_extract = &priv->extract.qos_key_extract; - key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); + if (dpaa2_flow_is_qos_flow_only(priv, attr.group) || + (actions && actions[0].type == RTE_FLOW_ACTION_TYPE_JUMP && + actions[1].type == RTE_FLOW_ACTION_TYPE_END)) { + qos_actions = actions; + goto qos_flow_create; + } - tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; - key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); + if (RTE_DPAA2_FLOW_GROUP_TYPE_GET(attr.group) == RTE_DPAA2_FS_GROUP_FLOW) + goto fs_flow_create; - /* Let's parse action on matching traffic */ - end_of_list = 0; - while (!end_of_list) { - switch (actions[j].type) { - case RTE_FLOW_ACTION_TYPE_QUEUE: - case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: - case RTE_FLOW_ACTION_TYPE_PORT_ID: - case RTE_FLOW_ACTION_TYPE_DROP: - ret = dpaa2_configure_flow_fs_action(priv, flow, - &actions[j]); - if (ret) - goto end_flow_set; - - /* Configure FS table first*/ - dist_size = priv->nb_rx_queues / priv->num_rx_tc; - if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_configure_fs_rss_table(priv, - flow->tc_id, - dist_size, - false); - if (ret) - goto end_flow_set; - } + jump_actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + if (actions[0].type == RTE_FLOW_ACTION_TYPE_JUMP) { + jump_actions[0].conf = actions[0].conf; + fs_action_idx++; + } else { + jump_tc.group = attr.group; + jump_actions[0].conf = &jump_tc; + } + jump_actions[1].type = RTE_FLOW_ACTION_TYPE_END; + qos_actions = jump_actions; + +qos_flow_create: + if (!priv->qos_entries) { + err_str = "No QoS entry available!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + qos_flow = dpaa2_flow_create_steering_flow(dev, &attr, pattern, + qos_actions, error, DPAA2_FLOW_QOS_TYPE); + if (!qos_flow) { + err_str = "QoS flow create failed!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + flow->qos_flow = qos_flow; + if (dpaa2_flow_is_qos_flow_only(priv, attr.group)) + goto insert_flow; + +fs_flow_create: + if (!priv->fs_entries) { + err_str = "No FS entry available!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + + fs_flow = dpaa2_flow_create_steering_flow(dev, &attr, pattern, + &actions[fs_action_idx], error, DPAA2_FLOW_FS_TYPE); + if (!fs_flow) { + err_str = "FS flow create failed!"; + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_code = -EINVAL; + goto flow_failure; + } + flow->fs_flow = fs_flow; + +insert_flow: + /* New rules are inserted. */ + curr = LIST_FIRST(&priv->flows); + if (!curr) { + LIST_INSERT_HEAD(&priv->flows, flow, next); + } else { + while (LIST_NEXT(curr, next)) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, flow, next); + } - /* Configure QoS table then.*/ - if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_configure_qos_table(priv, false); - if (ret) - goto end_flow_set; - } + return (struct rte_flow *)flow; - if (priv->num_rx_tc > 1) { - ret = dpaa2_flow_add_qos_rule(priv, flow); - if (ret) - goto end_flow_set; - } +flow_failure: + if (!flow) + goto err_quit; - if (flow->tc_index >= priv->fs_entries) { - DPAA2_PMD_ERR("FS table with %d entries full", - priv->fs_entries); - return -1; - } + ret = dpaa2_flow_destroy_steering_flow(dev, flow->qos_flow); + if (ret) + DPAA2_PMD_ERR("%s: Failed(%d) to destroy QoS flow", __func__, ret); + ret = dpaa2_flow_destroy_steering_flow(dev, flow->fs_flow); + if (ret) + DPAA2_PMD_ERR("%s: Failed(%d) to destroy FS flow", __func__, ret); + ret = dpaa2_flow_destroy_rss_flow(dev, flow->rss_flow); + if (ret) + DPAA2_PMD_ERR("%s: Failed(%d) to destroy RSS flow", __func__, ret); - ret = dpaa2_flow_add_fs_rule(priv, flow); - if (ret) - goto end_flow_set; + rte_free(flow); - break; - case RTE_FLOW_ACTION_TYPE_RSS: - rss_conf = actions[j].conf; - flow->action_type = RTE_FLOW_ACTION_TYPE_RSS; - - ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types, - &tc_key_extract->dpkg); - if (ret < 0) { - DPAA2_PMD_ERR("TC[%d] distset RSS failed", - flow->tc_id); - goto end_flow_set; - } +err_quit: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(error, -err_code, error_type, NULL, err_str); - dist_size = rss_conf->queue_num; - if (is_keycfg_configured & DPAA2_FLOW_FS_TYPE) { - ret = dpaa2_configure_fs_rss_table(priv, - flow->tc_id, - dist_size, - true); - if (ret) - goto end_flow_set; - } + return NULL; +} - if (is_keycfg_configured & DPAA2_FLOW_QOS_TYPE) { - ret = dpaa2_configure_qos_table(priv, true); - if (ret) - goto end_flow_set; - } +static int +dpaa2_flow_destroy(struct rte_eth_dev *dev, + struct rte_flow *_flow, struct rte_flow_error *error) +{ + int ret = 0; + struct dpaa2_dev_flow *flow; + + RTE_SET_USED(error); + + flow = (struct dpaa2_dev_flow *)_flow; + LIST_REMOVE(flow, next); + ret |= dpaa2_flow_destroy_rss_flow(dev, flow->rss_flow); + ret |= dpaa2_flow_destroy_steering_flow(dev, flow->qos_flow); + ret |= dpaa2_flow_destroy_steering_flow(dev, flow->fs_flow); + if (!ret) + rte_free(flow); - ret = dpaa2_flow_add_qos_rule(priv, flow); - if (ret) - goto end_flow_set; + return ret; +} - ret = dpaa2_flow_add_fs_rule(priv, flow); - if (ret) - goto end_flow_set; +static int +dpaa2_flow_set_miss_actions(struct rte_eth_dev *dev, + uint32_t group, const struct rte_flow_group_attr *attr, + const struct rte_flow_action actions[], struct rte_flow_error *err) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + enum dpaa2_flow_dist_type dist_type = DPAA2_FLOW_NULL_TYPE; + int end_of_list = 0, i = 0, discard = false, err_code = 0; + int qos_flow_only; + const struct rte_flow_action_jump *action_jump = NULL; + const struct rte_flow_action_queue *dest_queue = NULL; + uint32_t group_id = 0; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + struct dpaa2_queue *miss_rxq = NULL; + uint8_t qos_tc = 0xff; + uint16_t qos_flow = 0xffff; + + RTE_SET_USED(attr); + + qos_flow_only = dpaa2_flow_is_qos_flow_only(priv, group); + group_id = RTE_DPAA2_FLOW_GROUP_ID_GET(group); + + if (group >= priv->num_rx_tc) { + if (!priv->qos_entries) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "No QoS table available!"; + goto failure_to_set_miss_actions; + } + dist_type = DPAA2_FLOW_QOS_TYPE; + } else { + if (qos_flow_only) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "No TC table available!"; + goto failure_to_set_miss_actions; + } + dist_type = DPAA2_FLOW_FS_TYPE; + } + while (!end_of_list) { + switch (actions[i].type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + dest_queue = actions[i].conf; + if (dest_queue->index >= dev->data->nb_rx_queues) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION_CONF; + err_code = -EINVAL; + err_str = "Queue index overflows"; + goto failure_to_set_miss_actions; + } + miss_rxq = priv->rx_vq[dest_queue->index]; break; - case RTE_FLOW_ACTION_TYPE_PF: - /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_JUMP: + action_jump = actions[i].conf; + break; + case RTE_FLOW_ACTION_TYPE_DROP: + discard = true; break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; break; default: - DPAA2_PMD_ERR("Invalid action type"); - ret = -ENOTSUP; + DPAA2_PMD_WARN("Invalid default action type[%d]:(%d)", + i, actions[i].type); break; } - j++; + i++; } -end_flow_set: - if (!ret) { - /* New rules are inserted. */ - if (!curr) { - LIST_INSERT_HEAD(&priv->flows, flow, next); - } else { - while (LIST_NEXT(curr, next)) - curr = LIST_NEXT(curr, next); - LIST_INSERT_AFTER(curr, flow, next); + if (dist_type == DPAA2_FLOW_QOS_TYPE) { + if (action_jump && miss_rxq) { + if (action_jump->group != miss_rxq->tc_index) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Jump group conflicts to miss queue's TC"; + goto failure_to_set_miss_actions; + } + } + if (action_jump) + qos_tc = action_jump->group; + if (miss_rxq) { + qos_tc = miss_rxq->tc_index; + qos_flow = miss_rxq->flow_id; + } + if ((!discard && qos_tc == 0xff) || + (discard && qos_tc != 0xff)) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Invalid miss action set for QoS table"; + goto failure_to_set_miss_actions; + } + err_code = dpaa2_flow_qos_table_set_default(priv, discard, qos_tc, qos_flow); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to set miss action for QoS table"; + goto failure_to_set_miss_actions; } - } - - rte_free(dpaa2_pattern); - - return ret; -} - -static inline int -dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr, - const struct rte_flow_attr *attr) -{ - int ret = 0; - if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) { - DPAA2_PMD_ERR("Group/TC(%d) is out of range(%d)", - attr->group, dpni_attr->num_rx_tcs); - ret = -ENOTSUP; + return 0; } - if (unlikely(attr->priority >= dpni_attr->fs_entries)) { - DPAA2_PMD_ERR("Priority(%d) within group is out of range(%d)", - attr->priority, dpni_attr->fs_entries); - ret = -ENOTSUP; + + if (!discard && !miss_rxq) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Invalid miss action set for FS table"; + goto failure_to_set_miss_actions; } - if (unlikely(attr->egress)) { - DPAA2_PMD_ERR("Egress flow configuration is not supported"); - ret = -ENOTSUP; + if (miss_rxq && miss_rxq->tc_index != group_id) { + error_type = RTE_FLOW_ERROR_TYPE_ATTR_GROUP; + err_code = -EINVAL; + err_str = "Group conflicts with dest queue's TC ID"; + goto failure_to_set_miss_actions; } - if (unlikely(!attr->ingress)) { - DPAA2_PMD_ERR("Ingress flag must be configured"); - ret = -EINVAL; + err_code = dpaa2_flow_fs_table_set_default(priv, group_id, discard, + dest_queue ? dest_queue->index : 0); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Failed to set miss action for FS table"; } - return ret; + +failure_to_set_miss_actions: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + rte_flow_error_set(err, -err_code, error_type, NULL, err_str); + + return err_code; } -static inline int -dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[], - int sp_support) +static int +dpaa2_flow_steering_flow_action_update(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, + const struct rte_flow_action actions[], + struct rte_flow_error *error, + enum dpaa2_flow_dist_type dist_type) { - uint32_t i, j, is_found = 0; - int ret = 0; - const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + int err_code = 0; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; - hp_supported = dpaa2_hp_supported_pattern_type; - hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); + RTE_SET_USED(dev); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); + err_code = dpaa2_flow_steering_action_convert(flow, actions); + if (err_code) { + DPAA2_PMD_ERR("%s: steering action update failed(%d)", + __func__, err_code); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to QoS action update!"; - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { - is_found = 0; - for (i = 0; i < hp_supported_num; i++) { - if (hp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - if (is_found) - continue; - if (sp_support) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } - if (!is_found) { - DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); - ret = -ENOTSUP; - break; - } + goto quit; } - return ret; + err_code = dpaa2_flow_add_steering_rule(flow, true); + if (err_code) { + DPAA2_PMD_ERR("Failed(%d) to update %s flow entry", + err_code, dist_type == DPAA2_FLOW_QOS_TYPE ? "QoS" : "FS"); + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update action of entry to HW!"; + } + +quit: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + return rte_flow_error_set(error, -err_code, error_type, NULL, err_str); } -static inline int -dpaa2_dev_verify_actions(const struct rte_flow_action actions[]) +static int +dpaa2_flow_actions_update(struct rte_eth_dev *dev, + struct rte_flow *_flow, + const struct rte_flow_action actions[], + struct rte_flow_error *error) { - unsigned int i, j, is_found = 0; - int ret = 0; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_flow *flow; + int found = false, err_code = 0; + uint16_t update_num; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; + const char *err_str = NULL; + enum rte_flow_action_type supported; + struct rte_flow_action actions_update[DPAA2_MAX_ACTION_PER_FLOW_NUM]; + + LIST_FOREACH(flow, &priv->flows, next) { + if ((struct rte_flow *)flow == _flow) { + found = true; + break; + } + } + if (!found) { + DPAA2_PMD_ERR("%s: Flow(%p) is not in %s's flow list", + __func__, flow, dev->data->name); + error_type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED; + err_str = "Invalid flow for action update!"; + err_code = -EINVAL; + goto quit; + } + + /* check for the valid flow */ + flow = (void *)_flow; + + supported = RTE_FLOW_ACTION_TYPE_RSS; + update_num = dpaa2_flow_check_actions_support(actions, + &supported, 1, actions_update); + if (flow->rss_flow && update_num) { + err_code = dpaa2_flow_rss_action_update(dev, flow->rss_flow, NULL, actions, error); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update rss action!"; + goto quit; + } + } - for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { - for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) { - if (dpaa2_supported_action_type[i] == actions[j].type) { - is_found = 1; - break; - } + supported = RTE_FLOW_ACTION_TYPE_JUMP; + update_num = dpaa2_flow_check_actions_support(actions, + &supported, 1, actions_update); + if (flow->qos_flow && flow->fs_flow && update_num) { + err_code = dpaa2_flow_steering_flow_action_update(dev, flow->qos_flow, + actions_update, error, DPAA2_FLOW_QOS_TYPE); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update qos action!"; + goto quit; } - if (!is_found) { - ret = -ENOTSUP; - break; + } + + update_num = dpaa2_flow_check_actions_support(actions, + dpaa2_supported_qos_action_type, + RTE_DIM(dpaa2_supported_qos_action_type), + actions_update); + if (flow->qos_flow && !flow->fs_flow && update_num) { + err_code = dpaa2_flow_steering_flow_action_update(dev, flow->qos_flow, + actions_update, error, DPAA2_FLOW_QOS_TYPE); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update qos action!"; + goto quit; } } - for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) { - if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP && - !actions[j].conf) - ret = -EINVAL; + + update_num = dpaa2_flow_check_actions_support(actions, + dpaa2_supported_fs_action_type, + RTE_DIM(dpaa2_supported_fs_action_type), + actions_update); + if (flow->fs_flow && update_num) { + err_code = dpaa2_flow_steering_flow_action_update(dev, flow->qos_flow, + actions_update, error, DPAA2_FLOW_FS_TYPE); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update fs action!"; + goto quit; + } } - return ret; + +quit: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + return rte_flow_error_set(error, -err_code, error_type, NULL, err_str); } +/** + * Destroy user-configured flow rules. + * + * This function skips internal flows rules. + * + * @see rte_flow_flush() + * @see rte_flow_ops + */ static int -dpaa2_flow_validate(struct rte_eth_dev *dev, - const struct rte_flow_attr *flow_attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) +dpaa2_flow_flush(struct rte_eth_dev *dev, + struct rte_flow_error *error) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct dpni_attr dpni_attr; - struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; - uint16_t token = priv->token; + struct dpaa2_dev_flow *flow = LIST_FIRST(&priv->flows); int ret = 0; - memset(&dpni_attr, 0, sizeof(struct dpni_attr)); - ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr); - if (ret < 0) { - DPAA2_PMD_ERR("Get dpni@%d attribute failed(%d)", - priv->hw_id, ret); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ATTR, - flow_attr, "invalid"); - return ret; - } + while (flow) { + struct dpaa2_dev_flow *next = LIST_NEXT(flow, next); - /* Verify input attributes */ - ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid attributes are given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ATTR, - flow_attr, "invalid"); - goto not_valid_params; - } - /* Verify input pattern list */ - ret = dpaa2_dev_verify_patterns(pattern, priv->sp_protocol); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid pattern list is given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ITEM, - pattern, "invalid"); - goto not_valid_params; - } - /* Verify input action list */ - ret = dpaa2_dev_verify_actions(actions); - if (ret < 0) { - DPAA2_PMD_ERR("Invalid action list is given"); - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_ACTION, - actions, "invalid"); - goto not_valid_params; + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error); + if (ret) { + DPAA2_PMD_ERR("%s: Remove flow failed(%d)", + __func__, ret); + } + + flow = next; } -not_valid_params: + return ret; } -static struct rte_flow * -dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) +static int +dpaa2_flow_query(struct rte_eth_dev *dev, + struct rte_flow *_flow, const struct rte_flow_action *actions, + void *data, struct rte_flow_error *error) { - struct dpaa2_dev_flow *flow = NULL; + struct dpaa2_dev_flow *flow; struct dpaa2_dev_priv *priv = dev->data->dev_private; - int ret; - uint64_t iova; - - dpaa2_flow_control_log = - getenv("DPAA2_FLOW_CONTROL_LOG"); - - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), - RTE_CACHE_LINE_SIZE); - if (!flow) { - DPAA2_PMD_ERR("Failure to allocate memory for flow"); - goto mem_failure; - } + uint16_t num = 0, num_rsp, i, tc_id = 0; + int ret = 0, found = false; + size_t size, iova; + struct dpni_dump_table_rsp *rsp = NULL; - /* Allocate DMA'ble memory to write the qos rules */ - flow->qos_key_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->qos_key_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_key_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for qos key(%p)", - __func__, flow->qos_key_addr); - goto mem_failure; - } - flow->qos_rule.key_iova = iova; + RTE_SET_USED(actions); + RTE_SET_USED(data); + RTE_SET_USED(error); - flow->qos_mask_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->qos_mask_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->qos_mask_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); + flow = LIST_FIRST(&priv->flows); + while (flow) { + num++; + if (flow == (struct dpaa2_dev_flow *)_flow) + found = true; + flow = LIST_NEXT(flow, next); + } + if (!num || found == false) + return -ENXIO; + num = num * 2;/** Max: FS entry + QoS entry.*/ + flow = (void *)_flow; + size = sizeof(struct dpni_dump_table_header) + + num * sizeof(struct dpni_dump_table_entry); + rsp = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + if (!rsp) + return -ENOMEM; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(rsp, size); if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for qos mask(%p)", - __func__, flow->qos_mask_addr); - goto mem_failure; + DPAA2_PMD_ERR("%s: No IOMMU map for dump table result!", + __func__); + ret = -EIO; + goto quit; } - flow->qos_rule.mask_iova = iova; - /* Allocate DMA'ble memory to write the FS rules */ - flow->fs_key_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->fs_key_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_key_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for fs key(%p)", - __func__, flow->fs_key_addr); - goto mem_failure; - } - flow->fs_rule.key_iova = iova; + if (priv->num_rx_tc <= 1) + goto dump_fs; - flow->fs_mask_addr = rte_zmalloc(NULL, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE, RTE_CACHE_LINE_SIZE); - if (!flow->fs_mask_addr) { - DPAA2_PMD_ERR("Memory allocation failed"); - goto mem_failure; - } - iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(flow->fs_mask_addr, - DPAA2_EXTRACT_ALLOC_KEY_MAX_SIZE); - if (iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for fs mask(%p)", - __func__, flow->fs_mask_addr); - goto mem_failure; + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_QOS_TABLE, 0/**Any*/, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's QoS table failed(%d)", + dev->data->name, ret); + goto quit; } - flow->fs_rule.mask_iova = iova; - priv->curr = flow; + if (!flow->qos_flow) + goto dump_fs; - ret = dpaa2_generic_flow_set(flow, dev, attr, pattern, actions, error); - if (ret < 0) { - if (error && error->type > RTE_FLOW_ERROR_TYPE_ACTION) - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - attr, "unknown"); - DPAA2_PMD_ERR("Create flow failed (%d)", ret); - goto creation_error; + for (i = 0; i < num_rsp; i++) { + if (!memcmp(rsp->entry[i].key, flow->qos_flow->key_addr, + flow->qos_flow->rule_size) && + !memcmp(rsp->entry[i].mask, + flow->qos_flow->mask_addr, flow->qos_flow->rule_size)) + break; } - priv->curr = NULL; - return (struct rte_flow *)flow; - -mem_failure: - rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "memory alloc"); +dump_fs: + if (!flow->fs_flow) + goto quit; -creation_error: - if (flow) { - rte_free(flow->qos_key_addr); - rte_free(flow->qos_mask_addr); - rte_free(flow->fs_key_addr); - rte_free(flow->fs_mask_addr); - rte_free(flow); + tc_id = flow->fs_flow->tc_id; + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_FS_TABLE, tc_id, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's FS%d table failed(%d)", + dev->data->name, tc_id, ret); + goto quit; + } + for (i = 0; i < num_rsp; i++) { + if (!memcmp(rsp->entry[i].key, flow->fs_flow->key_addr, + flow->fs_flow->rule_size) && + !memcmp(rsp->entry[i].mask, + flow->fs_flow->mask_addr, flow->fs_flow->rule_size)) { + break; + } } - priv->curr = NULL; - return NULL; +quit: + if (rsp) + rte_free(rsp); + + return ret; } static int -dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, - struct rte_flow_error *error) +dpaa2_flow_table_dump_check(struct dpni_dump_table_rsp *rsp, + uint16_t num_rsp, char *dump_str, uint32_t str_size, int type, + struct dpaa2_dev_flow *_flow, uint16_t size) { - int ret = 0; + uint16_t i, j, off = 0; + int found, ret = 0; + uint8_t *key, *mask; struct dpaa2_dev_flow *flow; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; - flow = (struct dpaa2_dev_flow *)_flow; - - switch (flow->action_type) { - case RTE_FLOW_ACTION_TYPE_QUEUE: - case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: - case RTE_FLOW_ACTION_TYPE_PORT_ID: - case RTE_FLOW_ACTION_TYPE_DROP: - if (priv->num_rx_tc > 1) { - /* Remove entry from QoS table first */ - ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, - priv->token, - &flow->qos_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove FS QoS entry failed"); - dpaa2_flow_qos_entry_log("Delete failed", flow, - -1); - abort(); - goto error; - } + for (i = 0; i < num_rsp; i++) { + off += snprintf(&dump_str[off], str_size - off, + "entry%d: idx(%d):action(%d)\nkey:\n", + i, rsp->entry[i].rule_index, + rsp->entry[i].key_action); + for (j = 0; j < size; j++) { + off += snprintf(&dump_str[off], str_size - off, "%02x ", + rsp->entry[i].key[j]); } - - /* Then remove entry from FS table */ - ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token, - flow->tc_id, &flow->fs_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove entry from FS[%d] failed", - flow->tc_id); - goto error; + off += snprintf(&dump_str[off], str_size - off, "\nmask:\n"); + for (j = 0; j < size; j++) { + off += snprintf(&dump_str[off], str_size - off, "%02x ", + rsp->entry[i].mask[j]); } - break; - case RTE_FLOW_ACTION_TYPE_RSS: - if (priv->num_rx_tc > 1) { - ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, - priv->token, - &flow->qos_rule); - if (ret < 0) { - DPAA2_PMD_ERR("Remove RSS QoS entry failed"); - goto error; + off += snprintf(&dump_str[off], str_size - off, "\n"); + found = false; + flow = _flow; + while (flow) { + if (type == DPAA2_FLOW_QOS_TYPE) { + key = flow->qos_flow->key_addr; + mask = flow->qos_flow->mask_addr; + } else { + key = flow->fs_flow->key_addr; + mask = flow->fs_flow->mask_addr; + } + if (!memcmp(rsp->entry[i].key, key, size) && + !memcmp(rsp->entry[i].mask, mask, size)) { + found = true; + break; } + flow = LIST_NEXT(flow, next); + } + if (!found) { + off += snprintf(&dump_str[off], str_size - off, + "This entry not found in flow list\n"); + ret = -ENXIO; } - break; - default: - DPAA2_PMD_ERR("Action(%d) not supported", flow->action_type); - ret = -ENOTSUP; - break; } - LIST_REMOVE(flow, next); - rte_free(flow->qos_key_addr); - rte_free(flow->qos_mask_addr); - rte_free(flow->fs_key_addr); - rte_free(flow->fs_mask_addr); - /* Now free the flow */ - rte_free(flow); - -error: - if (ret) - rte_flow_error_set(error, EPERM, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, "unknown"); return ret; } -/** - * Destroy user-configured flow rules. - * - * This function skips internal flows rules. - * - * @see rte_flow_flush() - * @see rte_flow_ops - */ -static int -dpaa2_flow_flush(struct rte_eth_dev *dev, - struct rte_flow_error *error) +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_flow_table_query, 24.11) +int +rte_pmd_dpaa2_flow_table_query(uint16_t portid) { - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct dpaa2_dev_flow *flow = LIST_FIRST(&priv->flows); + struct rte_eth_dev *dev; + struct dpaa2_dev_flow *flow; + struct dpaa2_dev_priv *priv; + uint16_t num = 0, num_rsp, tc_id = 0; + int ret = 0, fs_enable[MAX_TCS]; + size_t size, iova; + struct dpni_dump_table_rsp *rsp = NULL; + char *dump_str = NULL; + uint16_t fs_rule_size[MAX_TCS], qos_rule_size; + struct dpaa2_generic_flow *_flow; + + if (!rte_pmd_dpaa2_dev_is_dpaa2(portid)) + return -EINVAL; - while (flow) { - struct dpaa2_dev_flow *next = LIST_NEXT(flow, next); + dev = &rte_eth_devices[portid]; + priv = dev->data->dev_private; - dpaa2_flow_destroy(dev, (struct rte_flow *)flow, error); - flow = next; + memset(fs_enable, 0, sizeof(fs_enable)); + memset(fs_rule_size, 0, sizeof(fs_rule_size)); + qos_rule_size = 0; + flow = LIST_FIRST(&priv->flows); + while (flow) { + if (!flow->fs_flow) + goto next_flow; + _flow = flow->fs_flow; + fs_enable[_flow->tc_id]++; + if (fs_rule_size[_flow->tc_id] < _flow->rule_size) + fs_rule_size[_flow->tc_id] = _flow->rule_size; + if (qos_rule_size < _flow->rule_size) + qos_rule_size = _flow->rule_size; + num++; +next_flow: + flow = LIST_NEXT(flow, next); + } + if (!num) + return -ENXIO; + size = sizeof(struct dpni_dump_table_header) + + num * sizeof(struct dpni_dump_table_entry); + rsp = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + if (!rsp) + return -ENOMEM; + dump_str = rte_zmalloc(NULL, num * 1024, 0); + if (!dump_str) + goto quit; + iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(rsp, size); + if (iova == RTE_BAD_IOVA) { + DPAA2_PMD_ERR("%s: No IOMMU map for dump table result!", + __func__); + goto quit; } - return 0; -} -static int -dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, - struct rte_flow *_flow __rte_unused, - const struct rte_flow_action *actions __rte_unused, - void *data __rte_unused, - struct rte_flow_error *error __rte_unused) -{ - return 0; + if (priv->num_rx_tc <= 1) + goto dump_fs; + + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_QOS_TABLE, 0/**Any*/, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's QoS table failed(%d)", + dev->data->name, ret); + goto quit; + } + DPAA2_PMD_INFO("dump %s's QoS table: type(%d):num(%d-%d):max(%d)", + dev->data->name, + rte_be_to_cpu_16(rsp->hdr.table_type), num_rsp, + rte_be_to_cpu_16(rsp->hdr.table_num_entries), + rte_be_to_cpu_16(rsp->hdr.table_max_entries)); + ret = dpaa2_flow_table_dump_check(rsp, num_rsp, + dump_str, num * 1024, DPAA2_FLOW_QOS_TYPE, + LIST_FIRST(&priv->flows), qos_rule_size); + DPAA2_PMD_INFO("%s", dump_str); + if (ret) + goto quit; + +dump_fs: + if (!fs_enable[tc_id]) + goto dump_next_fs; + ret = dpni_dump_table(priv->hw, CMD_PRI_LOW, + priv->token, DPNI_FS_TABLE, tc_id, + iova, size, &num_rsp); + if (ret) { + DPAA2_PMD_ERR("dump %s's FS%d table failed(%d)", + dev->data->name, tc_id, ret); + goto dump_next_fs; + } + DPAA2_PMD_INFO("dump %s's FS%d table: type(%d):num(%d-%d):max(%d)", + dev->data->name, tc_id, + rte_be_to_cpu_16(rsp->hdr.table_type), num_rsp, + rte_be_to_cpu_16(rsp->hdr.table_num_entries), + rte_be_to_cpu_16(rsp->hdr.table_max_entries)); + ret = dpaa2_flow_table_dump_check(rsp, num_rsp, + dump_str, num * 1024, DPAA2_FLOW_FS_TYPE, + LIST_FIRST(&priv->flows), fs_rule_size[tc_id]); + DPAA2_PMD_INFO("%s", dump_str); + if (ret) + goto quit; +dump_next_fs: + tc_id++; + if (tc_id < MAX_TCS) + goto dump_fs; + +quit: + if (rsp) + rte_free(rsp); + if (dump_str) + rte_free(dump_str); + + return ret; } /** @@ -5414,19 +4538,46 @@ dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused, * Pointer to private structure. */ void -dpaa2_flow_clean(struct rte_eth_dev *dev) +dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id, + enum dpaa2_flow_dist_type type) { - struct dpaa2_dev_flow *flow; + struct dpaa2_dev_flow *flow, *next_flow; struct dpaa2_dev_priv *priv = dev->data->dev_private; + int ret; - while ((flow = LIST_FIRST(&priv->flows))) - dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + flow = LIST_FIRST(&priv->flows); + if (tc_id >= MAX_TCS) + goto clean_all; + while (flow) { + next_flow = LIST_NEXT(flow, next); + if (((type & DPAA2_FLOW_QOS_TYPE) && flow->qos_flow) || + ((type & DPAA2_FLOW_FS_TYPE) && flow->fs_flow && + flow->fs_flow->tc_id == tc_id) || + ((type & DPAA2_FLOW_RSS_TYPE) && flow->rss_flow && + flow->rss_flow->tc_id == tc_id)) { + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + if (ret) + DPAA2_PMD_ERR("Failed(%d) to remove flow(type=%x)", ret, type); + } + flow = next_flow; + } + return; + +clean_all: + while (flow) { + ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); + if (ret) + DPAA2_PMD_ERR("Failed(%d) to remove flow", ret); + flow = LIST_FIRST(&priv->flows); + } } const struct rte_flow_ops dpaa2_flow_ops = { .create = dpaa2_flow_create, .validate = dpaa2_flow_validate, .destroy = dpaa2_flow_destroy, + .group_set_miss_actions = dpaa2_flow_set_miss_actions, + .actions_update = dpaa2_flow_actions_update, .flush = dpaa2_flow_flush, .query = dpaa2_flow_query, }; diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h index f07a70a826..7baf471ac0 100644 --- a/drivers/net/dpaa2/dpaa2_parser_decode.h +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -14,6 +14,7 @@ #define ROCEV2_DEST_QP_SIZE 3 enum dpaa2_parser_protocol_id { + DPAA2_PARSER_NULL_ID, DPAA2_PARSER_MAC_ID, DPAA2_PARSER_VLAN_ID, DPAA2_PARSER_ICMP_ID, @@ -26,6 +27,8 @@ enum dpaa2_parser_protocol_id { DPAA2_PARSER_TCP_ID, DPAA2_PARSER_SCTP_ID, DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_MPLS_ID, + DPAA2_PARSER_PPPOE_ID, DPAA2_PARSER_IPSEC_AH_ID, DPAA2_PARSER_IPSEC_ESP_ID, DPAA2_PARSER_VXLAN_ID, @@ -718,6 +721,12 @@ dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, } else if (protocol == DPAA2_PARSER_GTP_ID) { faf_h.gtp = 1; *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_MPLS_ID) { + faf_l.mpls_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_PPPOE_ID) { + faf_l.pppoe_ppp = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { faf_h.ipsec_esp = 1; *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index a6441eed65..f8718db0dc 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -146,6 +146,65 @@ const char * rte_pmd_dpaa2_ep_name(uint32_t eth_id); __rte_experimental int +rte_pmd_dpaa2_flow_table_query(uint16_t port_id); +__rte_experimental +int rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off); + +/** RTE_DPAA2_MIX_GROUP_FLOW has same behavio as RTE_DPAA2_FLAT_GROUP_FLOW*/ +enum rte_dpaa2_flow_type { + RTE_DPAA2_FLAT_GROUP_FLOW, + RTE_DPAA2_QOS_GROUP_FLOW = 1 << 0, + RTE_DPAA2_FS_GROUP_FLOW = 1 << 1, + RTE_DPAA2_MIX_GROUP_FLOW = + (RTE_DPAA2_QOS_GROUP_FLOW | RTE_DPAA2_FS_GROUP_FLOW) +}; + +#define RTE_PMD_DPAA2_FLOW_GROUP_TYPE_OFFSET 8 +#define RTE_PMD_DPAA2_FLOW_GROUP_ID_MASK \ + ((((uint32_t)1) << RTE_PMD_DPAA2_FLOW_GROUP_TYPE_OFFSET) - 1) + +#define RTE_DPAA2_FLOW_GROUP_TYPE_SET(group, type) \ + ((group) |= ((type) << RTE_PMD_DPAA2_FLOW_GROUP_TYPE_OFFSET)) + +#define RTE_DPAA2_FLOW_GROUP_TYPE_GET(group) \ + ((group) >> RTE_PMD_DPAA2_FLOW_GROUP_TYPE_OFFSET) + +#define RTE_DPAA2_FLOW_GROUP_ID_GET(group) \ + ((group) & RTE_PMD_DPAA2_FLOW_GROUP_ID_MASK) + +static inline struct rte_flow * +rte_dpaa2_flow_create(uint16_t port_id, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error, enum rte_dpaa2_flow_type type) +{ + struct rte_flow_attr _attr; + + rte_memcpy(&_attr, attr, sizeof(struct rte_flow_attr)); + RTE_DPAA2_FLOW_GROUP_TYPE_SET(_attr.group, type); + return rte_flow_create(port_id, &_attr, pattern, actions, error); +} + +static inline int +rte_dpaa2_flow_validate(uint16_t port_id, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_flow_error *error, enum rte_dpaa2_flow_type type) +{ + struct rte_flow_attr _attr; + + rte_memcpy(&_attr, attr, sizeof(struct rte_flow_attr)); + RTE_DPAA2_FLOW_GROUP_TYPE_SET(_attr.group, type); + return rte_flow_validate(port_id, &_attr, pattern, actions, error); +} + +__rte_experimental +int +rte_dpaa2_flow_group_set_miss_actions(uint16_t port_id, + uint32_t group_id, uint32_t type, const struct rte_flow_group_attr *attr, + const struct rte_flow_action actions[], struct rte_flow_error *error); #endif /* _RTE_PMD_DPAA2_H */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 22/65] net/dpaa2: reimplement RSS distribution via rte_flow 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (20 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 21/65] net/dpaa2: rework flow with per-table profile and group types Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 23/65] net/dpaa2: expand IP address extracts for RSS hashing Prashant Gupta ` (42 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Prefer the stable rte_flow API over driver-private, experimental entry points for RSS setup, and retire the private helpers that duplicated what rte_flow already does. The goal is that user code configures DPAA2 RSS the same way it configures any other PMD, with no reliance on experimental or vendor-specific interfaces. Delete drivers/net/dpaa2/base/dpaa2_hw_dpni.c and drop it from meson.build. The helpers it hosted (dpaa2_setup_flow_dist, dpaa2_setup_flow_dist_size, dpaa2_remove_flow_dist, dpaa2_distset_to_dpkg_profile_cfg, dpaa2_attach_bp_list, rte_pmd_dpaa2_set_custom_hash) are either reimplemented in dpaa2_ethdev.c or fully superseded by rte_flow. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 8 + drivers/net/dpaa2/base/dpaa2_hw_dpni.c | 544 ------------------------- drivers/net/dpaa2/dpaa2_ethdev.c | 297 +++++++++++--- drivers/net/dpaa2/dpaa2_ethdev.h | 21 - drivers/net/dpaa2/meson.build | 1 - drivers/net/dpaa2/rte_pmd_dpaa2.h | 84 ++-- 6 files changed, 311 insertions(+), 644 deletions(-) delete mode 100644 drivers/net/dpaa2/base/dpaa2_hw_dpni.c diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 70266464d2..9f9008f51b 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -228,6 +228,14 @@ API Changes Also, make sure to start the actual text at the margin. ======================================================= +* net/dpaa2: The exported function ``rte_pmd_dpaa2_set_custom_hash()`` is no + longer provided as a stable ABI symbol. A ``static inline`` helper of the + same name is still available in the DPAA2 public header, but it is now + implemented purely on top of the standard ``rte_flow`` API and no longer + depends on any DPAA2-specific internals. The inline helper is provided only + as a reference for users; applications should prefer calling the + ``rte_flow`` API directly. + * eal: Improved pointer arithmetic macros. * ``RTE_PTR_ADD``, ``RTE_PTR_SUB``, ``RTE_PTR_ALIGN``, ``RTE_PTR_ALIGN_CEIL``, diff --git a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c b/drivers/net/dpaa2/base/dpaa2_hw_dpni.c deleted file mode 100644 index 5f4268f0d7..0000000000 --- a/drivers/net/dpaa2/base/dpaa2_hw_dpni.c +++ /dev/null @@ -1,544 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. - * Copyright 2016-2021,2023-2025 NXP - * - */ - -#include <time.h> -#include <net/if.h> - -#include <eal_export.h> -#include <rte_mbuf.h> -#include <ethdev_driver.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <rte_cycles.h> -#include <rte_kvargs.h> -#include <dev_driver.h> - -#include <dpaa2_pmd_logs.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_mempool.h> - -#include "../dpaa2_ethdev.h" - -int -dpaa2_distset_to_dpkg_profile_cfg( - uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg); - -RTE_EXPORT_SYMBOL(rte_pmd_dpaa2_set_custom_hash) -int -rte_pmd_dpaa2_set_custom_hash(uint16_t port_id, - uint16_t offset, uint8_t size) -{ - struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id]; - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; - struct dpni_rx_tc_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret, tc_index = 0; - - if (!rte_eth_dev_is_valid_port(port_id)) { - DPAA2_PMD_WARN("Invalid port id %u", port_id); - return -EINVAL; - } - - if (strcmp(eth_dev->device->driver->name, - RTE_STR(NET_DPAA2_PMD_DRIVER_NAME))) { - DPAA2_PMD_WARN("Not a valid dpaa2 port"); - return -EINVAL; - } - - p_params = rte_zmalloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(&kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); - kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_DATA; - kg_cfg.extracts[0].extract.from_data.offset = offset; - kg_cfg.extracts[0].extract.from_data.size = size; - kg_cfg.extracts[0].num_of_byte_masks = 0; - kg_cfg.num_extracts = 1; - - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.dist_size = eth_dev->data->nb_rx_queues; - tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; - - ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, - &tc_cfg); - rte_free(p_params); - if (ret) { - DPAA2_PMD_ERR("Set RX TC dist failed(err=%d)", ret); - return ret; - } - - return 0; -} - -int -dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - int tc_dist_queues; - - /* TC distribution size is set with dist_queues or - * (nb_rx_queues - tc_index*dist_queues) in order of TC priority index. - */ - tc_dist_queues = eth_dev->data->nb_rx_queues - - tc_index * priv->dist_queues; - if (tc_dist_queues <= 0) { - DPAA2_PMD_INFO("No distribution on TC%d", tc_index); - return 0; - } - - if (tc_dist_queues > priv->dist_queues) - tc_dist_queues = priv->dist_queues; - - return dpaa2_setup_flow_dist_size(eth_dev, req_dist_set, - tc_index, tc_dist_queues); -} - -int -dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index, uint16_t dist_size) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = eth_dev->process_private; - struct dpni_rx_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret; - - if (dist_size == 0) - return 0; - - p_params = rte_malloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(p_params, 0, DIST_PARAM_IOVA_SIZE); - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - - ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg); - if (ret) { - DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported", - req_dist_set); - rte_free(p_params); - return ret; - } - - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.dist_size = dist_size; - tc_cfg.enable = true; - tc_cfg.tc = tc_index; - - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); - rte_free(p_params); - if (ret) { - DPAA2_PMD_ERR("RX Hash dist for failed(err=%d)", ret); - return ret; - } - - if (tc_index < MAX_TCS) - priv->dist_size_cur[tc_index] = dist_size; - - return 0; -} - -int -dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev, - uint8_t tc_index) -{ - struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct fsl_mc_io *dpni = priv->hw; - struct dpni_rx_dist_cfg tc_cfg; - struct dpkg_profile_cfg kg_cfg; - void *p_params; - int ret; - - p_params = rte_malloc(NULL, - DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); - if (!p_params) { - DPAA2_PMD_ERR("Unable to allocate flow-dist parameters"); - return -ENOMEM; - } - - memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg)); - tc_cfg.dist_size = 0; - tc_cfg.key_cfg_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(p_params, - DIST_PARAM_IOVA_SIZE); - if (tc_cfg.key_cfg_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for key cfg(%p)", - __func__, p_params); - rte_free(p_params); - return -ENOBUFS; - } - - tc_cfg.enable = true; - tc_cfg.tc = tc_index; - - memset(p_params, 0, DIST_PARAM_IOVA_SIZE); - kg_cfg.num_extracts = 0; - ret = dpkg_prepare_key_cfg(&kg_cfg, p_params); - if (ret) { - DPAA2_PMD_ERR("Unable to prepare extract parameters"); - rte_free(p_params); - return ret; - } - - ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, - &tc_cfg); - rte_free(p_params); - if (ret) - DPAA2_PMD_ERR("RX hash dist failed(err=%d)", ret); - return ret; -} - -int -dpaa2_distset_to_dpkg_profile_cfg( - uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg) -{ - uint32_t loop = 0, i = 0; - uint64_t dist_field = 0; - int l2_configured = 0, l3_configured = 0; - int l4_configured = 0; - int mpls_configured = 0; - int vlan_configured = 0; - int esp_configured = 0; - int ah_configured = 0; - int pppoe_configured = 0; - - memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); - while (req_dist_set) { - if (req_dist_set % 2 != 0) { - dist_field = 1ULL << loop; - switch (dist_field) { - case RTE_ETH_RSS_L2_PAYLOAD: - case RTE_ETH_RSS_ETH: - if (l2_configured) - break; - l2_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_ETH; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_ETH_TYPE; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_PPPOE: - if (pppoe_configured) - break; - pppoe_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_PPPOE; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_PPPOE_SID; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_ESP: - if (esp_configured) - break; - esp_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IPSEC_ESP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IPSEC_ESP_SPI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_AH: - if (ah_configured) - break; - ah_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IPSEC_AH; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_IPSEC_AH_SPI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_C_VLAN: - case RTE_ETH_RSS_S_VLAN: - if (vlan_configured) - break; - vlan_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_VLAN; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_VLAN_TCI; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_MPLS: - - if (mpls_configured) - break; - mpls_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_1; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_2; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_MPLS; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_MPLS_MPLSL_N; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - case RTE_ETH_RSS_IPV4: - case RTE_ETH_RSS_FRAG_IPV4: - case RTE_ETH_RSS_NONFRAG_IPV4_OTHER: - case RTE_ETH_RSS_IPV6: - case RTE_ETH_RSS_FRAG_IPV6: - case RTE_ETH_RSS_NONFRAG_IPV6_OTHER: - case RTE_ETH_RSS_IPV6_EX: { - static const uint32_t ip_fields[] = { - NH_FLD_IP_SRC, NH_FLD_IP_DST, - NH_FLD_IP_PROTO }; - static const uint8_t ip_hdr_index[] = { - 0, (uint8_t)LAST_HDR_INDEX }; - unsigned int f, h; - - if (l3_configured) - break; - l3_configured = 1; - - /* Hash on the outer IP (index 0) and the innermost - * IP instance. A plain frame has a single IP header, - * so only the outer extract resolves; a tunnelled - * frame resolves both and is also spread on its inner - * IP. - */ - for (h = 0; h < RTE_DIM(ip_hdr_index); h++) - for (f = 0; f < RTE_DIM(ip_fields); f++) { - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_IP; - kg_cfg->extracts[i].extract.from_hdr.hdr_index = - ip_hdr_index[h]; - kg_cfg->extracts[i].extract.from_hdr.field = - ip_fields[f]; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - } - break; - } - - case RTE_ETH_RSS_NONFRAG_IPV4_TCP: - case RTE_ETH_RSS_NONFRAG_IPV6_TCP: - case RTE_ETH_RSS_NONFRAG_IPV4_UDP: - case RTE_ETH_RSS_NONFRAG_IPV6_UDP: - case RTE_ETH_RSS_IPV6_TCP_EX: - case RTE_ETH_RSS_IPV6_UDP_EX: - case RTE_ETH_RSS_NONFRAG_IPV4_SCTP: - case RTE_ETH_RSS_NONFRAG_IPV6_SCTP: - - if (l4_configured) - break; - l4_configured = 1; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_TCP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_TCP_PORT_SRC; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - - kg_cfg->extracts[i].extract.from_hdr.prot = - NET_PROT_TCP; - kg_cfg->extracts[i].extract.from_hdr.field = - NH_FLD_TCP_PORT_DST; - kg_cfg->extracts[i].type = - DPKG_EXTRACT_FROM_HDR; - kg_cfg->extracts[i].extract.from_hdr.type = - DPKG_FULL_FIELD; - i++; - break; - - default: - DPAA2_PMD_WARN( - "unsupported flow dist option 0x%" PRIx64, - dist_field); - return -EINVAL; - } - } - req_dist_set = req_dist_set >> 1; - loop++; - } - kg_cfg->num_extracts = i; - return 0; -} - -int -dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, - struct fsl_mc_io *dpni, void *blist) -{ - /* Function to attach a DPNI with a buffer pool list. Buffer pool list - * handle is passed in blist. - */ - int32_t retcode; - struct dpni_pools_cfg bpool_cfg; - struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist; - struct dpni_buffer_layout layout; - int tot_size; - - /* ... rx buffer layout . - * Check alignment for buffer layouts first - */ - - /* ... rx buffer layout ... */ - if (priv->tx_conf_type == DPAA2_TX_DYNAMIC_CONF) { - int out_min_hdr_room, in_min_hdr_room; - /** Additional headroom layout for IPSec with TX configure - * dynamic enabled. - */ - in_min_hdr_room = DPAA2_RX_MIN_FD_OFFSET + - DPAA2_SEC_SIMPLE_FD_IB_MIN; - out_min_hdr_room = DPAA2_DYN_TX_MIN_FD_OFFSET + - DPAA2_SEC_SIMPLE_FD_OB_MIN; - tot_size = RTE_MAX(in_min_hdr_room, out_min_hdr_room); - if (tot_size < RTE_PKTMBUF_HEADROOM) - tot_size = RTE_PKTMBUF_HEADROOM; - } else { - tot_size = RTE_PKTMBUF_HEADROOM; - } - tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN); - - memset(&layout, 0, sizeof(struct dpni_buffer_layout)); - layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | - DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | - DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | - DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | - DPNI_BUF_LAYOUT_OPT_TIMESTAMP | - DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; - - layout.pass_timestamp = true; - layout.pass_frame_status = 1; - layout.private_data_size = DPAA2_FD_PTA_SIZE; - layout.pass_parser_result = 1; - layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN; - layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - - DPAA2_MBUF_HW_ANNOTATION; - retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX, &layout); - if (retcode) { - DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)", - retcode); - return retcode; - } - - /*Attach buffer pool to the network interface as described by the user*/ - memset(&bpool_cfg, 0, sizeof(struct dpni_pools_cfg)); - bpool_cfg.num_dpbp = 1; - bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; - bpool_cfg.pools[0].backup_pool = 0; - bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size, - DPAA2_PACKET_LAYOUT_ALIGN); - bpool_cfg.pools[0].priority_mask = 0; - - retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg); - if (retcode != 0) { - DPAA2_PMD_ERR("Error configuring buffer pool on interface." - " bpid = %d error code = %d", - bpool_cfg.pools[0].dpbp_id, retcode); - return retcode; - } - - priv->bp_list = bp_list; - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 9ad4494ab0..0de8e5c627 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -160,7 +160,7 @@ static int total_nb_rx_desc; */ #define DPAA2_RETA_SIZE 64 -/* Values of dist_size accepted by the DPNI 'dpni_set_rx_hash_dist' MC command. +/* Values of dist_size accepted by the DPNI HW requirement. * Source: fsl_dpni.h, "struct dpni_rx_dist_cfg::dist_size" documentation. * Used by dpaa2_dev_rss_reta_update() to validate user-requested patterns. */ @@ -172,11 +172,34 @@ static const uint16_t dpaa2_dist_size_allowed[] = { static bool dpaa2_dist_size_is_supported(uint16_t n) { - size_t i; + size_t i, offset = 0; + char print_buf[1024]; + int ret; + + ret = snprintf(print_buf, sizeof(print_buf), + "dist_size %u not supported by HW. Allowed: ", n); + if (ret > 0 && (size_t)ret < sizeof(print_buf)) + offset = (size_t)ret; + for (i = 0; i < RTE_DIM(dpaa2_dist_size_allowed); i++) { if (dpaa2_dist_size_allowed[i] == n) return true; + + /* Keep scanning the table even once the message buffer is + * full so a valid size is still matched; just stop appending. + */ + if (offset >= sizeof(print_buf) - 1) + continue; + + ret = snprintf(&print_buf[offset], sizeof(print_buf) - offset, + "%s%u", (i > 0) ? ", " : "", dpaa2_dist_size_allowed[i]); + if (ret > 0) + offset += (size_t)ret; + if (offset >= sizeof(print_buf)) + offset = sizeof(print_buf) - 1; } + DPAA2_PMD_ERR("%s", print_buf); + return false; } @@ -442,6 +465,189 @@ static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev); static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev); static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); +static int +dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, + uint64_t req_dist_set, int tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + int tc_dist_queues; + struct rte_flow_attr attr; + struct rte_flow_action_rss action_rss; + struct rte_flow_action actions[2]; + struct rte_flow *rss_flow; + + /*TC distribution size is set with dist_queues or + * nb_rx_queues % dist_queues in order of TC priority index. + * Calculating dist size for this tc_index:- + */ + tc_dist_queues = eth_dev->data->nb_rx_queues - + tc_index * priv->dist_queues; + if (tc_dist_queues <= 0) { + DPAA2_PMD_DEBUG("No distribution on TC%d", tc_index); + return 0; + } + + if (tc_dist_queues > priv->dist_queues) + tc_dist_queues = priv->dist_queues; + + memset(&attr, 0, sizeof(attr)); + action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT; + action_rss.level = 0; + action_rss.types = req_dist_set; + action_rss.key_len = 0; + action_rss.key = NULL; + action_rss.queue = NULL; + action_rss.queue_num = tc_dist_queues; + + actions[0].type = RTE_FLOW_ACTION_TYPE_RSS; + actions[0].conf = &action_rss; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + attr.group = tc_index; + attr.ingress = 1; + rss_flow = rte_flow_create(eth_dev->data->port_id, &attr, NULL, actions, NULL); + if (!rss_flow) { + DPAA2_PMD_WARN("%s: Set RSS flow dist on tc%d failed", + __func__, tc_index); + return -EIO; + } + + return 0; +} + +static int +dpaa2_remove_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint8_t tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile; + int ret; + + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (!tbl_profile->rss_flow) { + DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed", + eth_dev->data->name, tc_index); + return 0; + } + ret = rte_flow_destroy(eth_dev->data->port_id, tbl_profile->rss_flow, NULL); + if (ret) + return ret; + tbl_profile->rss_flow = NULL; + + return 0; +} + +static int +dpaa2_update_flow_rss_dist(struct rte_eth_dev *eth_dev, + uint64_t req_dist_set, int tc_index, uint16_t dist_size) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct dpaa2_flow_tbl_profile *tbl_profile; + struct rte_flow_action_rss action_rss; + struct rte_flow_action actions[2]; + int ret; + + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (!tbl_profile->rss_flow) { + DPAA2_PMD_WARN("%s'TC[%d] is not RSS distributed", + eth_dev->data->name, tc_index); + return 0; + } + action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT; + action_rss.level = 0; + action_rss.types = req_dist_set; + action_rss.key_len = 0; + action_rss.queue_num = dist_size; + action_rss.key = NULL; + action_rss.queue = NULL; + actions[0].type = RTE_FLOW_ACTION_TYPE_RSS; + actions[0].conf = &action_rss; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + ret = rte_flow_actions_update(eth_dev->data->port_id, tbl_profile->rss_flow, + actions, NULL); + if (!ret) + tbl_profile->tc_cfg.dist_size = dist_size; + + return ret; +} + +static int +dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, + struct fsl_mc_io *dpni, void *blist) +{ + /* Function to attach a DPNI with a buffer pool list. Buffer pool list + * handle is passed in blist. + */ + int32_t retcode; + struct dpni_pools_cfg bpool_cfg; + struct dpaa2_bp_list *bp_list = blist; + struct dpni_buffer_layout layout; + int tot_size, out_min_hdr_room, in_min_hdr_room; + + /* ... rx buffer layout . + * Check alignment for buffer layouts first + */ + + /* ... rx buffer layout ... */ + if (priv->tx_conf_type == DPAA2_TX_DYNAMIC_CONF) { + /** Additional headroom layout for IPSec with TX configure + * dynamic enabled. + */ + in_min_hdr_room = DPAA2_RX_MIN_FD_OFFSET + + DPAA2_SEC_SIMPLE_FD_IB_MIN; + out_min_hdr_room = DPAA2_DYN_TX_MIN_FD_OFFSET + + DPAA2_SEC_SIMPLE_FD_OB_MIN; + tot_size = RTE_MAX(in_min_hdr_room, out_min_hdr_room); + if (tot_size < RTE_PKTMBUF_HEADROOM) + tot_size = RTE_PKTMBUF_HEADROOM; + } else { + tot_size = RTE_PKTMBUF_HEADROOM; + } + tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN); + + memset(&layout, 0, sizeof(struct dpni_buffer_layout)); + layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | + DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | + DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | + DPNI_BUF_LAYOUT_OPT_DATA_ALIGN | + DPNI_BUF_LAYOUT_OPT_TIMESTAMP | + DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; + + layout.pass_timestamp = true; + layout.pass_frame_status = 1; + layout.private_data_size = DPAA2_FD_PTA_SIZE; + layout.pass_parser_result = 1; + layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN; + layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - + DPAA2_MBUF_HW_ANNOTATION; + retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token, + DPNI_QUEUE_RX, &layout); + if (retcode) { + DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)", + retcode); + return retcode; + } + + /*Attach buffer pool to the network interface as described by the user*/ + memset(&bpool_cfg, 0, sizeof(struct dpni_pools_cfg)); + bpool_cfg.num_dpbp = 1; + bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; + bpool_cfg.pools[0].backup_pool = 0; + bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size, + DPAA2_PACKET_LAYOUT_ALIGN); + bpool_cfg.pools[0].priority_mask = 0; + + retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg); + if (retcode) { + DPAA2_PMD_ERR("Error(%d) configuring bp(id=%d) on %s.", + retcode, bpool_cfg.pools[0].dpbp_id, + priv->eth_dev->data->name); + return retcode; + } + + priv->bp_list = bp_list; + return 0; +} + static int dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) { @@ -667,8 +873,8 @@ dpaa2_dev_info_get(struct rte_eth_dev *dev, /* DPAA2 has no software-visible indirection table: incoming packets are * dispatched to FQs via 'queue_id = hash % dist_size'. We expose the * standard RETA API as an emulation that only accepts uniform patterns - * 'reta[i] = i % N' and translates them into a dpni_set_rx_hash_dist - * command with dist_size=N. See dpaa2_dev_rss_reta_update(). + * 'reta[i] = i % N' and translates them into a DPNI HW command with + * dist_size=N. See dpaa2_dev_rss_reta_update(). */ dev_info->reta_size = DPAA2_RETA_SIZE; dev_info->hash_key_size = 0; @@ -2777,7 +2983,7 @@ dpaa2_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) static int dpaa2_dev_rss_hash_update(struct rte_eth_dev *dev, - struct rte_eth_rss_conf *rss_conf) + struct rte_eth_rss_conf *rss_conf) { struct rte_eth_dev_data *data = dev->data; struct dpaa2_dev_priv *priv = data->dev_private; @@ -2788,21 +2994,20 @@ dpaa2_dev_rss_hash_update(struct rte_eth_dev *dev, if (rss_conf->rss_hf) { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist(dev, rss_conf->rss_hf, - tc_index); + ret = dpaa2_update_flow_rss_dist(dev, rss_conf->rss_hf, + tc_index, priv->dist_queues); if (ret) { - DPAA2_PMD_ERR("Unable to set flow dist on tc%d", - tc_index); + DPAA2_PMD_ERR("Failed(%d) to set RSS flow on tc.%d", + ret, tc_index); return ret; } } } else { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_remove_flow_dist(dev, tc_index); + ret = dpaa2_remove_flow_rss_dist(dev, tc_index); if (ret) { - DPAA2_PMD_ERR( - "Unable to remove flow dist on tc%d", - tc_index); + DPAA2_PMD_ERR("Failed(%d) to remove RSS flow on tc.%d", + ret, tc_index); return ret; } } @@ -2813,21 +3018,17 @@ dpaa2_dev_rss_hash_update(struct rte_eth_dev *dev, static int dpaa2_dev_rss_hash_conf_get(struct rte_eth_dev *dev, - struct rte_eth_rss_conf *rss_conf) + struct rte_eth_rss_conf *rss_conf) { struct rte_eth_dev_data *data = dev->data; - struct rte_eth_conf *eth_conf = &data->dev_conf; /* dpaa2 does not support rss_key, so length should be 0*/ rss_conf->rss_key_len = 0; - rss_conf->rss_hf = eth_conf->rx_adv_conf.rss_conf.rss_hf; + rss_conf->rss_hf = data->dev_conf.rx_adv_conf.rss_conf.rss_hf; return 0; } -/* Emulation of the standard DPDK RETA API on top of DPAA2's - * dpni_set_rx_hash_dist MC command. - * - * DPAA2 hardware dispatches incoming frames using 'queue_id = hash % dist_size' +/* DPAA2 hardware dispatches incoming frames using 'queue_id = hash % dist_size' * (no software-visible indirection table). To expose the standard * rte_eth_dev_rss_reta_update() interface, we accept ONLY uniform patterns of * the form 'reta[i] = i % N' where N is in the HW-allowed dist_size list. Any @@ -2841,20 +3042,18 @@ dpaa2_dev_rss_hash_conf_get(struct rte_eth_dev *dev, */ static int dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, - struct rte_eth_rss_reta_entry64 *reta_conf, - uint16_t reta_size) + struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct rte_eth_conf *eth_conf = &dev->data->dev_conf; - uint16_t i, max_q = 0, n; + uint64_t req_dist_set = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; + uint16_t i, max_q = 0, n, grp, pos, q, expected; int tc_index, ret; bool any_set = false; PMD_INIT_FUNC_TRACE(); if (reta_size != DPAA2_RETA_SIZE) { - DPAA2_PMD_ERR("Invalid reta_size %u (expected %u)", - reta_size, DPAA2_RETA_SIZE); + DPAA2_PMD_ERR("Invalid reta_size %u (expected %u)", reta_size, DPAA2_RETA_SIZE); return -EINVAL; } @@ -2864,7 +3063,7 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, for (i = 0; i < reta_size / RTE_ETH_RETA_GROUP_SIZE; i++) { if (reta_conf[i].mask != UINT64_MAX) { DPAA2_PMD_ERR("partial RETA update not supported; set all %u entries", - DPAA2_RETA_SIZE); + DPAA2_RETA_SIZE); return -ENOTSUP; } } @@ -2873,9 +3072,8 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, * one slot to be selected via the per-group mask. */ for (i = 0; i < reta_size; i++) { - uint16_t grp = i / RTE_ETH_RETA_GROUP_SIZE; - uint16_t pos = i % RTE_ETH_RETA_GROUP_SIZE; - uint16_t q; + grp = i / RTE_ETH_RETA_GROUP_SIZE; + pos = i % RTE_ETH_RETA_GROUP_SIZE; if (!(reta_conf[grp].mask & (1ULL << pos))) continue; @@ -2902,10 +3100,9 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, * slot the user has selected. dpaa2 HW cannot honor any other layout. */ for (i = 0; i < reta_size; i++) { - uint16_t grp = i / RTE_ETH_RETA_GROUP_SIZE; - uint16_t pos = i % RTE_ETH_RETA_GROUP_SIZE; - uint16_t expected = i % n; - uint16_t q; + grp = i / RTE_ETH_RETA_GROUP_SIZE; + pos = i % RTE_ETH_RETA_GROUP_SIZE; + expected = i % n; if (!(reta_conf[grp].mask & (1ULL << pos))) continue; @@ -2921,18 +3118,12 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, } } - if (!dpaa2_dist_size_is_supported(n)) { - DPAA2_PMD_ERR("dist_size %u not supported by HW. Allowed: " - "1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,...", - n); + if (!dpaa2_dist_size_is_supported(n)) return -ENOTSUP; - } /* Apply on every configured RX TC, matching rss_hash_update behavior. */ for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist_size(dev, - eth_conf->rx_adv_conf.rss_conf.rss_hf, - tc_index, n); + ret = dpaa2_update_flow_rss_dist(dev, req_dist_set, tc_index, n); if (ret) { DPAA2_PMD_ERR("Failed to apply dist_size=%u on tc%d (err=%d)", n, tc_index, ret); @@ -2941,46 +3132,44 @@ dpaa2_dev_rss_reta_update(struct rte_eth_dev *dev, } DPAA2_PMD_DEBUG("RETA updated: dist_size now %u on %u TC(s)", - n, priv->num_rx_tc); + n, priv->num_rx_tc); return 0; } /* Synthesizes a RETA snapshot from the currently-active dist_size on TC 0. * Since DPAA2 always uses uniform 'hash mod N' distribution, the returned - * RETA is reta[i] = i % dist_size_cur[0]. + * RETA is reta[i] = i % flow_profile.tc_profile[0].tc_cfg.dist_size. */ static int dpaa2_dev_rss_reta_query(struct rte_eth_dev *dev, - struct rte_eth_rss_reta_entry64 *reta_conf, - uint16_t reta_size) + struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) { struct dpaa2_dev_priv *priv = dev->data->dev_private; - uint16_t i, n; + uint16_t i, n, grp, pos; PMD_INIT_FUNC_TRACE(); if (reta_size != DPAA2_RETA_SIZE) { DPAA2_PMD_ERR("Invalid reta_size %u (expected %u)", - reta_size, DPAA2_RETA_SIZE); + reta_size, DPAA2_RETA_SIZE); return -EINVAL; } /* Use the cached dist_size on TC 0 (representative). Fall back to the * default (nb_rx_queues clamped to dist_queues) when never programmed. */ - n = priv->dist_size_cur[0]; - if (n == 0) { + n = priv->flow_profile.tc_profile[0].tc_cfg.dist_size; + if (!n) { n = priv->dist_queues; if (n > dev->data->nb_rx_queues) n = dev->data->nb_rx_queues; } - if (n == 0) + if (!n) return -EINVAL; for (i = 0; i < reta_size; i++) { - uint16_t grp = i / RTE_ETH_RETA_GROUP_SIZE; - uint16_t pos = i % RTE_ETH_RETA_GROUP_SIZE; - + grp = i / RTE_ETH_RETA_GROUP_SIZE; + pos = i % RTE_ETH_RETA_GROUP_SIZE; if (reta_conf[grp].mask & (1ULL << pos)) reta_conf[grp].reta[pos] = i % n; } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e3fb3f8920..7a65f5e383 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -395,12 +395,6 @@ struct dpaa2_dev_priv { /** RXQs in same TC share same cgid.*/ uint8_t cgid_in_use[MAX_TCS]; - /* Current hash distribution size per RX TC, written by - * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. - * Zero means "use default" (= nb_rx_queues clamped to dist_queues). - */ - uint16_t dist_size_cur[MAX_TCS]; - uint16_t dpni_ver_major; uint16_t dpni_ver_minor; uint32_t speed_capa; @@ -876,21 +870,6 @@ dpaa2_dpkg_insert_extract(struct dpkg_profile_cfg *kg_cfg, kg_cfg->num_extracts++; } -int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, - struct dpkg_profile_cfg *kg_cfg); - -int dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index); - -int dpaa2_setup_flow_dist_size(struct rte_eth_dev *eth_dev, - uint64_t req_dist_set, int tc_index, uint16_t dist_size); - -int dpaa2_remove_flow_dist(struct rte_eth_dev *eth_dev, - uint8_t tc_index); - -int dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, - struct fsl_mc_io *dpni, void *blist); - __rte_internal int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, int eth_rx_queue_id, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index b821f7bfad..affcaf8d3a 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -8,7 +8,6 @@ endif deps += ['mempool_dpaa2'] sources = files( - 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', 'dpaa2_mux.c', diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index f8718db0dc..e8e21e28cc 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -13,6 +13,7 @@ #include <rte_compat.h> #include <rte_flow.h> +#include <ethdev_driver.h> /** * LX series support only. @@ -84,30 +85,6 @@ __rte_experimental int rte_pmd_dpaa2_mux_rx_frame_len(uint32_t dpdmux_id, uint16_t max_rx_frame_len); -/** - * Create a custom hash key on basis of offset of start of packet and size. - * for e.g. if we need GRE packets (non-vlan and without any extra headers) - * to be hashed on basis of inner IP header, we will provide offset as: - * 14 (eth) + 20 (IP) + 4 (GRE) + 12 (Inner Src offset) = 50 and size - * as 8 bytes. - * - * @param port_id - * The port identifier of the Ethernet device. - * @param offset - * Offset from the start of packet which needs to be included to - * calculate hash - * @param size - * Size of the hash input key - * - * @return - * - 0 if successful. - * - Negative in case of failure. - */ -int -rte_pmd_dpaa2_set_custom_hash(uint16_t port_id, - uint16_t offset, - uint8_t size); - /** * @warning * @b EXPERIMENTAL: this API may change, or be removed, without prior notice @@ -207,4 +184,63 @@ int rte_dpaa2_flow_group_set_miss_actions(uint16_t port_id, uint32_t group_id, uint32_t type, const struct rte_flow_group_attr *attr, const struct rte_flow_action actions[], struct rte_flow_error *error); + +__rte_experimental +static inline int +rte_pmd_dpaa2_set_custom_hash(uint16_t port_id, + uint16_t offset, uint8_t size) +{ + struct rte_flow *rss_flow; + struct rte_eth_dev *dev; + struct rte_flow_item_raw raw_spec; + struct rte_flow_item_raw raw_mask; + struct rte_flow_attr attr; + struct rte_flow_action_rss rss; + struct rte_flow_item pattern[2]; + struct rte_flow_action action[2]; + int ret; + + if (!rte_pmd_dpaa2_dev_is_dpaa2(port_id)) + return -EINVAL; + + dev = &rte_eth_devices[port_id]; + + memset(&attr, 0, sizeof(attr)); + memset(&raw_spec, 0, sizeof(raw_spec)); + memset(&raw_mask, 0, sizeof(raw_mask)); + + raw_spec.relative = 0; + raw_spec.search = 0; + raw_spec.offset = offset; + raw_spec.limit = 0; + raw_spec.length = size; + + raw_mask.offset = 0xffff; + raw_mask.length = 0xffff; + pattern[0].type = RTE_FLOW_ITEM_TYPE_RAW; + pattern[0].spec = &raw_spec; + pattern[0].mask = &raw_mask; + pattern[1].type = RTE_FLOW_ITEM_TYPE_END; + + memset(&rss, 0, sizeof(rss)); + rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT; + /** Assume single TC only, will rework later.*/ + rss.queue_num = dev->data->nb_rx_queues; + + attr.ingress = 1; + + action[0].type = RTE_FLOW_ACTION_TYPE_RSS; + action[0].conf = &rss; + action[1].type = RTE_FLOW_ACTION_TYPE_END; + + ret = rte_flow_validate(port_id, &attr, pattern, action, NULL); + if (ret) + return ret; + + rss_flow = rte_flow_create(port_id, &attr, pattern, action, NULL); + if (!rss_flow) + return -EINVAL; + + return 0; +} #endif /* _RTE_PMD_DPAA2_H */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 23/65] net/dpaa2: expand IP address extracts for RSS hashing 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (21 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 22/65] net/dpaa2: reimplement RSS distribution via rte_flow Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 24/65] net/dpaa2: add policer v2 MC command and L2/L3 byte units Prashant Gupta ` (41 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Maxime Leroy From: Jun Yang <jun.yang@nxp.com> When RSS distribution is enabled, hashing on an IP source or destination address should cover both the outermost and the innermost (last) IP header so that tunnelled and multi-layer IP traffic is spread correctly. The key configuration only described a single header index, so only one IP layer contributed to the hash. Add dpaa2_flow_dpkg_ip_addr_hdr_expand(), which copies the existing key extracts and, for every IP source/destination address extract, inserts a second extract with hdr_index set to LAST_HDR_INDEX. The TC table configuration now uses this expanded key configuration on the RSS distribution path, while the exact-match path keeps the original key. Move dpaa2_flow_is_ip_addr_extract() earlier so the new helper can use it, and change it to return a boolean since only the match result is needed. Also fix LAST_HDR_INDEX, which was defined as 0xFFFFFFFF but is written into the 8-bit hdr_index field of the MC key extract; use 0xFF so the "last header" marker is programmed correctly. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Maxime Leroy <maxime@leroys.fr> --- drivers/net/dpaa2/dpaa2_flow.c | 68 ++++++++++++++++++++++++++-------- drivers/net/dpaa2/mc/fsl_net.h | 4 +- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index a22af4f33b..dc2e821d75 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -2613,6 +2613,48 @@ dpaa2_flow_fs_table_set_default(struct dpaa2_dev_priv *priv, return 0; } +static int +dpaa2_flow_is_ip_addr_extract(const struct dpkg_extract *extract) +{ + enum dpkg_extract_type type = extract->type; + enum net_prot prot = extract->extract.from_hdr.prot; + uint32_t field = extract->extract.from_hdr.field; + + if (type == DPKG_EXTRACT_FROM_HDR && prot == NET_PROT_IP && + (field == NH_FLD_IP_SRC || field == NH_FLD_IP_DST)) + return true; + + return false; +} + +static int +dpaa2_flow_dpkg_ip_addr_hdr_expand(const struct dpkg_profile_cfg *dpkg, + struct dpkg_profile_cfg *rss_dpkg) +{ + uint8_t i; + + memset(rss_dpkg, 0, sizeof(struct dpkg_profile_cfg)); + for (i = 0; i < dpkg->num_extracts; i++) { + if ((rss_dpkg->num_extracts + 1) > DPKG_MAX_NUM_OF_EXTRACTS) + return -ENOSPC; + rte_memcpy(&rss_dpkg->extracts[rss_dpkg->num_extracts], + &dpkg->extracts[i], sizeof(struct dpkg_extract)); + rss_dpkg->extracts[rss_dpkg->num_extracts].extract.from_hdr.hdr_index = 0; + rss_dpkg->num_extracts++; + if (!dpaa2_flow_is_ip_addr_extract(&dpkg->extracts[i])) + continue; + if ((rss_dpkg->num_extracts + 1) > DPKG_MAX_NUM_OF_EXTRACTS) + return -ENOSPC; + rte_memcpy(&rss_dpkg->extracts[rss_dpkg->num_extracts], &dpkg->extracts[i], + sizeof(struct dpkg_extract)); + rss_dpkg->extracts[rss_dpkg->num_extracts].extract.from_hdr.hdr_index = + LAST_HDR_INDEX; + rss_dpkg->num_extracts++; + } + + return 0; +} + static int dpaa2_flow_tc_table_config(struct dpaa2_dev_priv *priv, uint8_t tc_id, int rss_dist, int enable) @@ -2624,6 +2666,8 @@ dpaa2_flow_tc_table_config(struct dpaa2_dev_priv *priv, struct fsl_mc_io *dpni = priv->hw; uint16_t entry_size; struct dpaa2_queue *queue; + const struct dpkg_profile_cfg *cfg; + struct dpkg_profile_cfg rss_extract; tbl_profile = &priv->flow_profile.tc_profile[tc_id]; if (tbl_profile->entry_num) { @@ -2645,7 +2689,15 @@ dpaa2_flow_tc_table_config(struct dpaa2_dev_priv *priv, } dpaa2_flow_extracts_log(priv, "Configure", tc_id); - ret = dpkg_prepare_key_cfg(&key_profile->dpkg, tbl_profile->extract_param); + if (rss_dist) { + ret = dpaa2_flow_dpkg_ip_addr_hdr_expand(&key_profile->dpkg, &rss_extract); + if (ret) + return ret; + cfg = &rss_extract; + } else { + cfg = &key_profile->dpkg; + } + ret = dpkg_prepare_key_cfg(cfg, tbl_profile->extract_param); if (ret < 0) { DPAA2_PMD_ERR("TC[%d] prepare key failed", tc_id); return ret; @@ -3251,20 +3303,6 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, return ret; } -static uint32_t -dpaa2_flow_is_ip_addr_extract(const struct dpkg_extract *extract) -{ - enum dpkg_extract_type type = extract->type; - enum net_prot prot = extract->extract.from_hdr.prot; - uint32_t field = extract->extract.from_hdr.field; - - if (type == DPKG_EXTRACT_FROM_HDR && prot == NET_PROT_IP && - (field == NH_FLD_IP_SRC || field == NH_FLD_IP_DST)) - return field; - - return 0; -} - static void dpaa2_flow_key_offset_size(struct dpaa2_key_profile *key_profile, uint8_t idx, uint8_t *offset, uint8_t *size) diff --git a/drivers/net/dpaa2/mc/fsl_net.h b/drivers/net/dpaa2/mc/fsl_net.h index 9ace8f3226..2aae0c99e2 100644 --- a/drivers/net/dpaa2/mc/fsl_net.h +++ b/drivers/net/dpaa2/mc/fsl_net.h @@ -1,14 +1,14 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2015 Freescale Semiconductor Inc. - * Copyright 2018-2019 NXP + * Copyright 2018-2019, 2026 NXP * */ #ifndef __FSL_NET_H #define __FSL_NET_H -#define LAST_HDR_INDEX 0xFFFFFFFF +#define LAST_HDR_INDEX 0xFF /*****************************************************************************/ /* Protocol fields */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 24/65] net/dpaa2: add policer v2 MC command and L2/L3 byte units 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (22 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 23/65] net/dpaa2: expand IP address extracts for RSS hashing Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 25/65] net/dpaa2: support rte_mtr and METER rte_flow action Prashant Gupta ` (40 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Pick up the v2 version of the DPNI SET_RX_TC_POLICING MC command and expose the new policer features it brings, while keeping support for older MC firmwares that only speak the v1 command. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/mc/dpni.c | 54 +++++++++++++++++++++------------ drivers/net/dpaa2/mc/fsl_dpni.h | 23 +++++++++++--- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index 54df66416a..8e4114e604 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -2210,30 +2210,16 @@ int dpni_clear_fs_entries(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } -/** - * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration - * @mc_io: Pointer to MC portal's I/O object - * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' - * @token: Token of DPNI object - * @tc_id: Traffic class selection (0-7) - * @cfg: Traffic class policing configuration - * - * Return: '0' on Success; error code otherwise. - */ -int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, - uint32_t cmd_flags, - uint16_t token, - uint8_t tc_id, - const struct dpni_rx_tc_policing_cfg *cfg) +static int +_dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg, uint16_t cmd_id) { struct dpni_cmd_set_rx_tc_policing *cmd_params; struct mc_command cmd = { 0 }; - /* prepare command */ - cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_POLICING, - cmd_flags, - token); - cmd_params = (struct dpni_cmd_set_rx_tc_policing *)cmd.params; + cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, token); + cmd_params = (void *)cmd.params; dpni_set_field(cmd_params->mode_color, COLOR, cfg->default_color); dpni_set_field(cmd_params->mode_color, MODE, cfg->mode); dpni_set_field(cmd_params->units, UNITS, cfg->units); @@ -2248,6 +2234,34 @@ int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, return mc_send_command(mc_io, &cmd); } +/** + * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPNI object + * @tc_id: Traffic class selection (0-7) + * @cfg: Traffic class policing configuration + * + * Return: '0' on Success; error code otherwise. + */ +int +dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg) +{ + return _dpni_set_rx_tc_policing(mc_io, cmd_flags, token, tc_id, cfg, + DPNI_CMDID_SET_RX_TC_POLICING); +} + +int +dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, uint16_t token, uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg) +{ + return _dpni_set_rx_tc_policing(mc_io, cmd_flags, token, tc_id, cfg, + DPNI_CMDID_SET_RX_TC_POLICING_V1); +} + /** * dpni_get_rx_tc_policing() - Get Rx traffic class policing configuration * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 4bec348545..9e6dc23f66 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1141,6 +1141,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ +#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004 + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1157,12 +1162,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1203,13 +1213,18 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); +int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 25/65] net/dpaa2: support rte_mtr and METER rte_flow action 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (23 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 24/65] net/dpaa2: add policer v2 MC command and L2/L3 byte units Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 26/65] net/dpaa2: program flow table miss actions via rte_flow Prashant Gupta ` (39 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add a traffic metering/policing path to the DPAA2 PMD that is driven entirely through the standard DPDK APIs: rte_mtr for profile/policy /meter object management and rte_flow METER / METER_MARK actions for binding a meter to a per-TC ingress flow. No DPAA2-specific or experimental entry points are introduced. - Add drivers/net/dpaa2/dpaa2_meter.c implementing struct rte_mtr_ops (capabilities_get, meter_profile_add/get/delete, meter_policy_add/get/delete, create, destroy, meter_profile_update, meter_policy_update) on top of the DPNI policer. Supported algorithms are RTE_MTR_NONE, RTE_MTR_TRTCM_RFC2698 and RTE_MTR_TRTCM_RFC4115, in both byte and packet mode, color-aware or blind. - Hook dpaa2_mtr_ops_get() into dpaa2_ethdev_ops.mtr_ops_get so applications reach the implementation via rte_mtr_ops_get() / rte_mtr_*(). Register the file in drivers/net/dpaa2/meson.build. - Extend struct dpaa2_dev_priv with LIST_HEADs for meter profiles, policies and meter objects, and a meter_lock spinlock to serialize concurrent rte_mtr calls. Add helper structs dpaa2_dev_meter_profile / _policy / _meter. - Extend struct dpaa2_flow_profile with per-TC meter bookkeeping (tc_mtr_profile[], mtr_flow[]) and add DPAA2_FLOW_METER_TYPE to enum dpaa2_flow_dist_type so the flow cleaner can tear meter flows down together with QoS/FS/RSS flows. - Wire the METER and METER_MARK rte_flow actions into dpaa2_flow.c: dpaa2_flow_validate() recognizes them, dpaa2_flow_create() routes such rules into a new dpaa2_flow_create_meter_flow() path, and dpaa2_flow_actions_update() updates the policer in place via dpaa2_flow_meter_action_update(). dpaa2_flow_destroy() / dpaa2_flow_clean() tear down meter flows and reset the TC policer to DPNI_POLICER_MODE_NONE. - dpaa2_flow_set_police_action() programs the HW policer via dpni_set_rx_tc_policing(), honoring the profile's mode/units/ CIR/CBS/PIR/PBS, the policy's RED action (drop vs. passthrough), and color_mode. Picks the v1 or v2 MC command based on the DPNI firmware revision, and preserves counters on update when the firmware supports DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS. - Add MC-rev gates DPAA2_POLICER_SET_V2_MC_REV and DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV so the driver falls back to dpni_set_rx_tc_policing_v1() on older firmware. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 1 + drivers/net/dpaa2/dpaa2_ethdev.h | 39 ++- drivers/net/dpaa2/dpaa2_flow.c | 327 ++++++++++++++++- drivers/net/dpaa2/dpaa2_meter.c | 584 +++++++++++++++++++++++++++++++ drivers/net/dpaa2/meson.build | 1 + 5 files changed, 948 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0de8e5c627..7cd83149dd 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3678,6 +3678,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, .timesync_read_time = dpaa2_timesync_read_time, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 7a65f5e383..0ad237a5cc 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -213,6 +213,8 @@ #define DPAA2_FLOW_FRM_REPLICATION_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 106) #define DPAA2_QOS_FLOW_TABLE_SET_V3_MC_REV RTE_FSL_MC_REV(10, 39, 109) #define DPAA2_QOS_FLOW_TABLE_MISS_FLOW_ACTION_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_POLICER_SET_V2_MC_REV RTE_FSL_MC_REV(10, 39, 109) +#define DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV DPAA2_POLICER_SET_V2_MC_REV #define DPAA2_MAC_XSTATS_MC_REV RTE_FSL_MC_REV(10, 39, 109) /* mac counters */ @@ -270,8 +272,9 @@ enum dpaa2_flow_dist_type { DPAA2_FLOW_QOS_TYPE = 1 << 0, DPAA2_FLOW_FS_TYPE = 1 << 1, DPAA2_FLOW_RSS_TYPE = 1 << 2, + DPAA2_FLOW_METER_TYPE = 1 << 3, DPAA2_FLOW_ALL_TYPE = (DPAA2_FLOW_QOS_TYPE | DPAA2_FLOW_FS_TYPE | - DPAA2_FLOW_RSS_TYPE) + DPAA2_FLOW_RSS_TYPE | DPAA2_FLOW_METER_TYPE) }; enum key_prot_type { @@ -340,6 +343,9 @@ struct dpaa2_flow_tbl_profile { struct dpaa2_flow_profile { struct dpaa2_flow_tbl_profile qos_profile; struct dpaa2_flow_tbl_profile tc_profile[MAX_TCS]; + /** Meter per TC.*/ + struct dpaa2_dev_meter_profile *tc_mtr_profile[MAX_TCS]; + void *mtr_flow[MAX_TCS]; void *mempool[MAX_TCS]; uint8_t bp_idx[MAX_TCS]; }; @@ -350,6 +356,30 @@ enum dpaa2_tx_conf_type { DPAA2_TX_DYNAMIC_CONF }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + int red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -395,6 +425,8 @@ struct dpaa2_dev_priv { /** RXQs in same TC share same cgid.*/ uint8_t cgid_in_use[MAX_TCS]; + rte_spinlock_t meter_lock; + uint16_t dpni_ver_major; uint16_t dpni_ver_minor; uint32_t speed_capa; @@ -443,6 +475,9 @@ struct dpaa2_dev_priv { union dpni_statistics pg_xstats[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -936,4 +971,6 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); + +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); #endif /* _DPAA2_ETHDEV_H */ diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index dc2e821d75..920e9edc51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -67,6 +67,7 @@ struct dpaa2_dev_flow { struct dpaa2_generic_flow *qos_flow; struct dpaa2_generic_flow *fs_flow; struct dpaa2_generic_flow *rss_flow; + struct dpaa2_generic_flow *meter_flow; }; struct dpaa2_flow_item { @@ -118,6 +119,11 @@ static const enum rte_flow_action_type dpaa2_supported_qos_action_type[] = { RTE_FLOW_ACTION_TYPE_JUMP }; +static const enum rte_flow_action_type dpaa2_supported_meter_action_type[] = { + RTE_FLOW_ACTION_TYPE_METER_MARK, + RTE_FLOW_ACTION_TYPE_METER +}; + #define DPAA2_FLOW_HDR_HEX_DUMP_SIZE \ (RTE_MAX(sizeof(struct rte_flow_item_eth), \ RTE_MAX(sizeof(struct rte_flow_item_vlan), \ @@ -360,6 +366,10 @@ dpaa2_flow_generic_flow(struct dpaa2_dev_flow *dev_flow, (dev_flow->rss_flow->tc_id == tc_id || tc_id >= MAX_TCS)) { return dev_flow->rss_flow; } + if (type == DPAA2_FLOW_METER_TYPE && dev_flow->meter_flow && + (dev_flow->meter_flow->tc_id == tc_id || tc_id >= MAX_TCS)) { + return dev_flow->meter_flow; + } return NULL; } @@ -2446,6 +2456,10 @@ dpaa2_flow_verify_flow_action(struct dpaa2_dev_priv *priv, /* Skip this action, have to add for vxlan*/ case RTE_FLOW_ACTION_TYPE_DROP: break; + case RTE_FLOW_ACTION_TYPE_METER_MARK: + break; + case RTE_FLOW_ACTION_TYPE_METER: + break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; break; @@ -2945,6 +2959,141 @@ dpaa2_flow_table_update(struct dpaa2_dev_priv *priv, return ret; } +static int +dpaa2_flow_action_meter_mark_init(struct dpaa2_dev_priv *priv, + uint32_t mtr_id, struct rte_flow_action_meter_mark *meter_mark) +{ + struct dpaa2_dev_meter *meter; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + int found = 0; + + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->meter_id == mtr_id) { + found = 1; + break; + } + meter = LIST_NEXT(meter, next); + } + + if (!found) { + DPAA2_PMD_ERR("Meter ID(%d) is not found!", mtr_id); + return -ENXIO; + } + + found = 0; + profile = LIST_FIRST(&priv->profiles); + while (profile) { + if (profile->profile_id == meter->profile_id) { + found = 1; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + DPAA2_PMD_ERR("Meter ID(%d)'s profile(%d) not exist!", + mtr_id, meter->profile_id); + return -ENXIO; + } + + found = 0; + policy = LIST_FIRST(&priv->policies); + while (policy) { + if (policy->policy_id == meter->policy_id) { + found = 1; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + /** Option.*/ + DPAA2_PMD_WARN("Meter ID(%d)'s policy(%d) not exist!", + mtr_id, meter->policy_id); + policy = NULL; + } + + meter_mark->profile = (void *)profile; + meter_mark->policy = (void *)policy; + meter_mark->color_mode = 1; + + return 0; +} + +static int +dpaa2_flow_set_police_action(struct dpaa2_dev_priv *priv, + uint8_t tc_id, const struct rte_flow_action_meter_mark *meter_mark) +{ + struct dpni_rx_tc_policing_cfg policing_cfg = {0}; + const struct dpaa2_dev_meter_profile *dpaa2_profile; + const struct dpaa2_dev_meter_policy *dpaa2_policy = NULL; + int ret; + + if (!(priv->options & DPNI_OPT_HAS_POLICING)) { + DPAA2_PMD_ERR("POLICING(0x%08x) was not added in DPNI creating options(0x%08x)", + DPNI_OPT_HAS_POLICING, priv->options); + return -ENOTSUP; + } + + dpaa2_profile = (void *)meter_mark->profile; + if (!dpaa2_profile) { + DPAA2_PMD_ERR("Meter profile not specified!"); + return -EINVAL; + } + + /** Blind as default.*/ + policing_cfg.options = 0; + if (meter_mark->color_mode) + policing_cfg.options = DPNI_POLICER_OPT_COLOR_AWARE; + if (meter_mark->policy) + dpaa2_policy = (void *)meter_mark->policy; + if (dpaa2_policy && dpaa2_policy->red_drop) { + policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + } else if (!dpaa2_policy) { + /** Default: Red is discarded if no policy specified.*/ + policing_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + } + + if (priv->flow_profile.mtr_flow[tc_id]) { + /** Update existing policer.*/ + policing_cfg.options |= DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS; + if (priv->mc_rev < DPAA2_POLICER_NOT_RESET_COUNTER_MC_REV) + DPAA2_PMD_WARN("The existing policer's counters will be cleaned."); + } + + policing_cfg.mode = dpaa2_profile->mode; + if (policing_cfg.mode < DPNI_POLICER_MODE_NONE || + policing_cfg.mode > DPNI_POLICER_MODE_RFC_4115) { + DPAA2_PMD_ERR("Invalid policer mode(%d)", + policing_cfg.mode); + return -EINVAL; + } + policing_cfg.units = dpaa2_profile->policer_unit; + if (policing_cfg.units < DPNI_POLICER_UNIT_BYTES_L3 || + policing_cfg.units > DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS) { + DPAA2_PMD_ERR("Invalid policer units(%d)", + policing_cfg.units); + return -EINVAL; + } + policing_cfg.cir = dpaa2_profile->cir; + policing_cfg.cbs = dpaa2_profile->cbs; + policing_cfg.eir = dpaa2_profile->pir; + policing_cfg.ebs = dpaa2_profile->pbs; + + if (priv->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &policing_cfg); + } else { + ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &policing_cfg); + } + DPAA2_PMD_INFO("%s RX TC%d policer configure %s.", + priv->eth_dev->data->name, tc_id, + ret ? "failed" : "successfully"); + + return ret; +} + static int dpaa2_flow_steering_action_convert(struct dpaa2_generic_flow *flow, const struct rte_flow_action actions[]) @@ -3233,15 +3382,25 @@ dpaa2_flow_validate(struct rte_eth_dev *dev, goto invalid_params; } + action_num = dpaa2_flow_check_actions_support(actions, + dpaa2_supported_meter_action_type, + RTE_DIM(dpaa2_supported_meter_action_type), NULL); + if (action_num) { + DPAA2_PMD_DEBUG("This is meter flow."); + if (pattern) + DPAA2_PMD_WARN("Meter flow ingores flow items!"); + goto meter_rss_check; + } + supported = RTE_FLOW_ACTION_TYPE_RSS; action_num = dpaa2_flow_check_actions_support(actions, &supported, 1, NULL); if (action_num) { DPAA2_PMD_DEBUG("This is rss flow."); - goto rss_check; + goto meter_rss_check; } goto verify_attr; -rss_check: +meter_rss_check: if (action_num > 1) { err_str = "Multiple flow's action."; cause = actions; @@ -3716,6 +3875,39 @@ dpaa2_flow_destroy_steering_flow(struct rte_eth_dev *dev, return ret; } +static int +dpaa2_flow_destroy_meter_flow(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *meter_flow) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + uint8_t tc_id; + + if (!meter_flow) + return 0; + + tc_id = meter_flow->tc_id; + RTE_ASSERT(priv->flow_profile.mtr_flow[tc_id] == meter_flow); + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = DPNI_POLICER_MODE_NONE; + if (priv->mc_rev < DPAA2_POLICER_SET_V2_MC_REV) { + ret = dpni_set_rx_tc_policing_v1(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &cfg); + } else { + ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, tc_id, &cfg); + } + if (ret) + return ret; + priv->flow_profile.tc_mtr_profile[tc_id] = NULL; + priv->flow_profile.mtr_flow[tc_id] = NULL; + + dpaa2_flow_generic_flow_deinit(meter_flow); + + return 0; +} + static int dpaa2_flow_destroy_rss_flow(struct rte_eth_dev *dev, struct dpaa2_generic_flow *flow) @@ -3835,7 +4027,7 @@ dpaa2_flow_create_rss_flow(struct rte_eth_dev *dev, if (ret) return NULL; - dpaa2_flow_clean(dev, tc, DPAA2_FLOW_FS_TYPE); + dpaa2_flow_clean(dev, tc, DPAA2_FLOW_FS_TYPE | DPAA2_FLOW_METER_TYPE); flow = dpaa2_flow_generic_flow_init(priv, 0, true, DPAA2_FLOW_RSS_TYPE, tc); @@ -3855,6 +4047,68 @@ dpaa2_flow_create_rss_flow(struct rte_eth_dev *dev, return NULL; } +static int +dpaa2_flow_set_meter_action(struct dpaa2_dev_priv *priv, + uint8_t tc, const struct rte_flow_action *meter_action, + struct rte_flow_action_meter_mark *meter_mark) +{ + const struct rte_flow_action_meter *meter; + int ret; + + if (meter_action[0].type == RTE_FLOW_ACTION_TYPE_METER_MARK) { + rte_memcpy(meter_mark, meter_action->conf, + sizeof(struct rte_flow_action_meter_mark)); + } else if (meter_action->type == RTE_FLOW_ACTION_TYPE_METER_MARK) { + meter = meter_action->conf; + ret = dpaa2_flow_action_meter_mark_init(priv, meter->mtr_id, meter_mark); + if (ret) + return ret; + } else { + return -EINVAL; + } + ret = dpaa2_flow_set_police_action(priv, tc, meter_mark); + + return ret; +} + +static struct dpaa2_generic_flow * +dpaa2_flow_create_meter_flow(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_action meter_action[]) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_generic_flow *flow = NULL; + struct rte_flow_action_meter_mark meter_mark; + int ret; + uint8_t tc; + + if (attr->group >= priv->num_rx_tc) + return NULL; + + if (priv->flow_profile.mtr_flow[attr->group]) + return NULL; + + flow = dpaa2_flow_generic_flow_init(priv, 0, true, + DPAA2_FLOW_METER_TYPE, attr->group); + if (!flow) + return NULL; + + tc = attr->group; + ret = dpaa2_flow_set_meter_action(priv, tc, meter_action, &meter_mark); + if (ret) + goto create_failure; + + priv->flow_profile.tc_mtr_profile[tc] = (void *)meter_mark.profile; + priv->flow_profile.mtr_flow[tc] = flow; + + return flow; +create_failure: + + dpaa2_flow_generic_flow_deinit(flow); + + return NULL; +} + static struct rte_flow * dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *pattr, @@ -3873,6 +4127,7 @@ dpaa2_flow_create(struct rte_eth_dev *dev, struct dpaa2_generic_flow *rss_flow = NULL; struct dpaa2_generic_flow *qos_flow = NULL; struct dpaa2_generic_flow *fs_flow = NULL; + struct dpaa2_generic_flow *meter_flow = NULL; enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_NONE; const char *err_str = NULL; @@ -3904,6 +4159,20 @@ dpaa2_flow_create(struct rte_eth_dev *dev, goto insert_flow; } + if (dpaa2_flow_check_actions_support(actions, + dpaa2_supported_meter_action_type, + RTE_DIM(dpaa2_supported_meter_action_type), NULL)) { + meter_flow = dpaa2_flow_create_meter_flow(dev, &attr, actions); + if (!meter_flow) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_code = -EINVAL; + err_str = "Failed to create meter flow!"; + goto flow_failure; + } + flow->meter_flow = meter_flow; + goto insert_flow; + } + if (dpaa2_flow_is_qos_flow_only(priv, attr.group) || (actions && actions[0].type == RTE_FLOW_ACTION_TYPE_JUMP && actions[1].type == RTE_FLOW_ACTION_TYPE_END)) { @@ -3988,6 +4257,9 @@ dpaa2_flow_create(struct rte_eth_dev *dev, ret = dpaa2_flow_destroy_rss_flow(dev, flow->rss_flow); if (ret) DPAA2_PMD_ERR("%s: Failed(%d) to destroy RSS flow", __func__, ret); + ret = dpaa2_flow_destroy_meter_flow(dev, flow->meter_flow); + if (ret) + DPAA2_PMD_ERR("%s: Failed(%d) to destroy meter flow", __func__, ret); rte_free(flow); @@ -4010,6 +4282,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, flow = (struct dpaa2_dev_flow *)_flow; LIST_REMOVE(flow, next); + ret |= dpaa2_flow_destroy_meter_flow(dev, flow->meter_flow); ret |= dpaa2_flow_destroy_rss_flow(dev, flow->rss_flow); ret |= dpaa2_flow_destroy_steering_flow(dev, flow->qos_flow); ret |= dpaa2_flow_destroy_steering_flow(dev, flow->fs_flow); @@ -4148,6 +4421,38 @@ dpaa2_flow_set_miss_actions(struct rte_eth_dev *dev, return err_code; } +static int +dpaa2_flow_meter_action_update(struct rte_eth_dev *dev, + struct dpaa2_generic_flow *flow, + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int err_code = 0; + uint8_t tc_id; + struct rte_flow_action_meter_mark meter_mark; + enum rte_flow_error_type error_type = RTE_FLOW_ERROR_TYPE_ACTION; + const char *err_str = NULL; + + /* check for the valid flow */ + tc_id = flow->tc_id; + if (priv->flow_profile.mtr_flow[tc_id] != flow) { + err_str = "The meter flow to update doesn't match!"; + err_code = -EINVAL; + goto quit; + } + err_code = dpaa2_flow_set_meter_action(priv, tc_id, actions, &meter_mark); + if (err_code) + err_str = "Failed to update meter action!"; + else + priv->flow_profile.tc_mtr_profile[tc_id] = (void *)meter_mark.profile; + +quit: + if (err_str) + DPAA2_PMD_ERR("%s: %s", __func__, err_str); + return rte_flow_error_set(error, -err_code, error_type, NULL, err_str); +} + static int dpaa2_flow_steering_flow_action_update(struct rte_eth_dev *dev, struct dpaa2_generic_flow *flow, @@ -4218,6 +4523,20 @@ dpaa2_flow_actions_update(struct rte_eth_dev *dev, /* check for the valid flow */ flow = (void *)_flow; + update_num = dpaa2_flow_check_actions_support(actions, + dpaa2_supported_meter_action_type, + RTE_DIM(dpaa2_supported_meter_action_type), + actions_update); + if (flow->meter_flow && update_num) { + err_code = dpaa2_flow_meter_action_update(dev, + flow->meter_flow, actions_update, error); + if (err_code) { + error_type = RTE_FLOW_ERROR_TYPE_ACTION; + err_str = "Failed to update meter action!"; + goto quit; + } + } + supported = RTE_FLOW_ACTION_TYPE_RSS; update_num = dpaa2_flow_check_actions_support(actions, &supported, 1, actions_update); @@ -4591,6 +4910,8 @@ dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id, if (((type & DPAA2_FLOW_QOS_TYPE) && flow->qos_flow) || ((type & DPAA2_FLOW_FS_TYPE) && flow->fs_flow && flow->fs_flow->tc_id == tc_id) || + ((type & DPAA2_FLOW_METER_TYPE) && flow->meter_flow && + flow->meter_flow->tc_id == tc_id) || ((type & DPAA2_FLOW_RSS_TYPE) && flow->rss_flow && flow->rss_flow->tc_id == tc_id)) { ret = dpaa2_flow_destroy(dev, (struct rte_flow *)flow, NULL); diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..463cc2156e --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,584 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2026 NXP + */ + +#include <sys/queue.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +#define DPAA2_METER_ERR_MSG_LEN 128 +static char s_err_msg[DPAA2_METER_ERR_MSG_LEN]; + +static void __rte_format_printf(1, 2) +dpaa2_meter_err_msg(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(s_err_msg, DPAA2_METER_ERR_MSG_LEN, fmt, ap); + va_end(ap); +} + +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = true, + .color_aware_trtcm_rfc4115_supported = true, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (!capa) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter\n"); + } + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (!dpaa2_profile) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!\n"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /** Align with DPNI policy.*/ + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else if (profile->packet_mode > DPNI_POLICER_UNIT_FRAMES) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + dpaa2_profile->profile_id = profile_id; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + if (!curr) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next)) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + int red_drop = 0; + + if (policy->actions[RTE_COLOR_GREEN]) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!\n"); + } + if (policy->actions[RTE_COLOR_YELLOW]) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!\n"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = 1; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + dpaa2_meter_err_msg("Meter red policy action(%d) NOT supported!\n", + red_action->type); + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (!dpaa2_policy) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!\n"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + if (!curr) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next)) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter, *tmp; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (!dpaa2_profile) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->profile_id == profile_id) { + DPAA2_PMD_INFO("Meter(id=%d) with profile(%d) is removed!", + meter->meter_id, profile_id); + tmp = meter; + meter = LIST_NEXT(meter, next); + LIST_REMOVE(tmp, next); + rte_free(tmp); + } else { + meter = LIST_NEXT(meter, next); + } + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter, *tmp; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (!dpaa2_policy) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid.\n"); + } + + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->policy_id == policy_id) { + DPAA2_PMD_INFO("Meter(id=%d) with policy(%d) is removed!", + meter->meter_id, policy_id); + tmp = meter; + meter = LIST_NEXT(meter, next); + LIST_REMOVE(tmp, next); + rte_free(tmp); + } else { + meter = LIST_NEXT(meter, next); + } + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + int found = 0, ret = 0; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + + RTE_SET_USED(shared); + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile) { + if (profile->profile_id == profile_id) { + found = 1; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + dpaa2_meter_err_msg("Meter profile ID(%d) not exist!\n", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = 0; + policy = LIST_FIRST(&priv->policies); + while (policy) { + if (policy->policy_id == policy_id) { + found = 1; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + dpaa2_meter_err_msg("Meter policy ID(%d) not exist!\n", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->meter_id == mtr_id) { + dpaa2_meter_err_msg("Meter ID(%d) exist!\n", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } else { + meter = LIST_NEXT(meter, next); + } + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (!meter) { + dpaa2_meter_err_msg("Meter memory alloc failed!\n"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + curr = LIST_FIRST(&priv->meters); + if (!curr) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next)) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + dpaa2_meter_err_msg("Meter ID(%d) does not exist!\n", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + int found = 0, ret = 0; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->meter_id == mtr_id) { + found = 1; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + dpaa2_meter_err_msg("Meter ID(%d) not found!\n", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = 0; + profile = LIST_FIRST(&priv->profiles); + while (profile) { + if (profile->profile_id == profile_id) { + found = 1; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + dpaa2_meter_err_msg("Profile ID(%d) not found!\n", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + int found = 0, ret = 0; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter) { + if (meter->meter_id == mtr_id) { + found = 1; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + dpaa2_meter_err_msg("Meter ID(%d) not found!\n", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = 0; + policy = LIST_FIRST(&priv->policies); + while (policy) { + if (policy->policy_id == policy_id) { + found = 1; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + dpaa2_meter_err_msg("Profile ID(%d) not found!\n", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + rte_spinlock_init(&priv->meter_lock); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index affcaf8d3a..b5bff519af 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -16,6 +16,7 @@ sources = files( 'dpaa2_recycle.c', 'dpaa2_rxtx.c', 'dpaa2_ptp.c', + 'dpaa2_meter.c', 'mc/dprtc.c', 'mc/dpkg.c', 'mc/dpdmux.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 26/65] net/dpaa2: program flow table miss actions via rte_flow 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (24 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 25/65] net/dpaa2: support rte_mtr and METER rte_flow action Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 27/65] net/dpaa2: support DCB Rx mode " Prashant Gupta ` (38 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Push the per-table "miss" behavior for the DPAA2 QoS and FS tables through the standard rte_flow_group_set_miss_actions() API instead of leaving it implicit, and tidy up the surrounding dev-ops code. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 440 +++++++++++++++++-------------- 1 file changed, 243 insertions(+), 197 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 7cd83149dd..9f92789d4e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -459,11 +459,52 @@ static const struct rte_eth_stats dpaa2_stats_xstat_ids = { #define DPAA2_MAC_XSTATS_START_ID DPAA2_DPNI_XSTAT_MAX_NUM static struct rte_dpaa2_driver rte_dpaa2_pmd; -static int dpaa2_dev_link_update(struct rte_eth_dev *dev, - int wait_to_complete); -static int dpaa2_dev_set_link_up(struct rte_eth_dev *dev); -static int dpaa2_dev_set_link_down(struct rte_eth_dev *dev); -static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); + +static int +dpaa2_setup_table_miss_action(struct rte_eth_dev *eth_dev, + uint8_t tc_index) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct rte_flow_group_attr attr; + struct rte_flow_action actions[2]; + struct dpaa2_flow_tbl_profile *tbl_profile; + + memset(&attr, 0, sizeof(attr)); + attr.ingress = 1; + if (tc_index < priv->num_rx_tc) { + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + if (tbl_profile->default_drop) { + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else if (tbl_profile->default_queue.index >= eth_dev->data->nb_rx_queues) { + DPAA2_PMD_DEBUG("%s-tc%d-default-rxq(%d) >= max rxq(%d), Force to drop.", + eth_dev->data->name, tc_index, tbl_profile->default_queue.index, + eth_dev->data->nb_rx_queues); + tbl_profile->default_drop = true; + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else { + actions[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; + actions[0].conf = &tbl_profile->default_queue; + } + } else { + tbl_profile = &priv->flow_profile.qos_profile; + if (tbl_profile->default_drop) { + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else if (tbl_profile->default_jump.group >= priv->num_rx_tc) { + DPAA2_PMD_DEBUG("%s-default-tc(%d) >= max tc(%d), Force to drop.", + eth_dev->data->name, tbl_profile->default_jump.group, + priv->num_rx_tc); + tbl_profile->default_drop = true; + actions[0].type = RTE_FLOW_ACTION_TYPE_DROP; + } else { + actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + actions[0].conf = &tbl_profile->default_jump; + } + } + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + + return rte_flow_group_set_miss_actions(eth_dev->data->port_id, + tc_index, &attr, actions, NULL); +} static int dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, @@ -1162,18 +1203,14 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) /* Rx offloads which are enabled by default */ if (dev_rx_offloads_nodis & ~rx_offloads) { - DPAA2_PMD_INFO( - "Some of rx offloads enabled by default - requested 0x%" PRIx64 - " fixed are 0x%" PRIx64, - rx_offloads, dev_rx_offloads_nodis); + DPAA2_PMD_INFO("RX offloads requested/fixed: 0x%" PRIx64 "/0x%" PRIx64, + rx_offloads, dev_rx_offloads_nodis); } /* Tx offloads which are enabled by default */ if (dev_tx_offloads_nodis & ~tx_offloads) { - DPAA2_PMD_INFO( - "Some of tx offloads enabled by default - requested 0x%" PRIx64 - " fixed are 0x%" PRIx64, - tx_offloads, dev_tx_offloads_nodis); + DPAA2_PMD_INFO("TX offloads requested/fixed: 0x%" PRIx64 "/0x%" PRIx64, + tx_offloads, dev_tx_offloads_nodis); } max_rx_pktlen = eth_conf->rxmode.mtu + RTE_ETHER_HDR_LEN + @@ -1181,16 +1218,31 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) if (max_rx_pktlen <= DPAA2_MAX_RX_PKT_LEN) { ret = dpni_set_max_frame_length(dpni, CMD_PRI_LOW, priv->token, max_rx_pktlen - RTE_ETHER_CRC_LEN); - if (ret != 0) { + if (ret) { DPAA2_PMD_ERR("Unable to set mtu. check config"); return ret; } DPAA2_PMD_DEBUG("MTU configured for the device: %d", dev->data->mtu); } else { - DPAA2_PMD_ERR("Configured mtu %d and calculated max-pkt-len is %d which should be <= %d", - eth_conf->rxmode.mtu, max_rx_pktlen, DPAA2_MAX_RX_PKT_LEN); - return -1; + DPAA2_PMD_ERR("MAX MTU(%d) to configure > %d", + max_rx_pktlen, DPAA2_MAX_RX_PKT_LEN); + return -ENOTSUP; + } + + if (priv->fs_entries) { + for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { + ret = dpaa2_setup_table_miss_action(dev, tc_index); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-tc%d table", + ret, dev->data->name, tc_index); + } + } + } + ret = dpaa2_setup_table_miss_action(dev, priv->num_rx_tc); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-QoS table", + ret, dev->data->name); } if (eth_conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) { @@ -1784,6 +1836,171 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) return NULL; } +/* return 0 means link status changed, -1 means not changed */ +static int +dpaa2_dev_link_update(struct rte_eth_dev *dev, + int wait_to_complete) +{ + int ret; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = dev->process_private; + struct rte_eth_link link; + struct dpni_link_state state = {0}; + uint8_t count; + + if (!dpni) { + DPAA2_PMD_ERR("dpni is NULL"); + return 0; + } + + for (count = 0; count <= MAX_REPEAT_TIME; count++) { + ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state); + if (ret < 0) { + DPAA2_PMD_DEBUG("error: dpni_get_link_state %d", ret); + return ret; + } + if (state.up == RTE_ETH_LINK_DOWN && + wait_to_complete) + rte_delay_ms(CHECK_INTERVAL); + else + break; + } + + memset(&link, 0, sizeof(struct rte_eth_link)); + link.link_status = state.up; + link.link_speed = state.rate; + + if (state.options & DPNI_LINK_OPT_HALF_DUPLEX) + link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX; + else + link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; + + ret = rte_eth_linkstatus_set(dev, &link); + if (ret < 0) { + DPAA2_PMD_DEBUG("No change in status"); + } else { + DPAA2_PMD_INFO("Port %d Link is %s", dev->data->port_id, + link.link_status ? "Up" : "Down"); + } + + return ret; +} + +/** + * Toggle the DPNI to enable, if not already enabled. + * This is not strictly PHY up/down - it is more of logical toggling. + */ +static int +dpaa2_dev_set_link_up(struct rte_eth_dev *dev) +{ + int ret, en = 0; + struct dpaa2_dev_priv *priv; + struct fsl_mc_io *dpni; + struct dpni_link_state state = {0}; + + priv = dev->data->dev_private; + dpni = dev->process_private; + + if (!dpni) { + DPAA2_PMD_ERR("dpni is NULL"); + return -ENODEV; + } + + /* Check if DPNI is currently enabled */ + ret = dpni_is_enabled(dpni, CMD_PRI_LOW, priv->token, &en); + if (ret) { + /* Unable to obtain dpni status; Not continuing */ + DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret); + return ret; + } + + /* Enable link if not already enabled */ + if (!en) { + ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token); + if (ret) { + DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret); + return ret; + } + } + ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state); + if (ret < 0) { + DPAA2_PMD_DEBUG("Unable to get link state (%d)", ret); + return ret; + } + + /* changing tx burst function to start enqueues */ + dev->tx_pkt_burst = dpaa2_dev_tx; + dev->data->dev_link.link_status = state.up; + dev->data->dev_link.link_speed = state.rate; + + if (state.options & DPNI_LINK_OPT_HALF_DUPLEX) + dev->data->dev_link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX; + else + dev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; + + if (state.up) + DPAA2_PMD_DEBUG("Port %d Link is Up", dev->data->port_id); + else + DPAA2_PMD_DEBUG("Port %d Link is Down", dev->data->port_id); + return ret; +} + +/** + * Toggle the DPNI to disable, if not already disabled. + * This is not strictly PHY up/down - it is more of logical toggling. + */ +static int +dpaa2_dev_set_link_down(struct rte_eth_dev *dev) +{ + int ret, dpni_enabled = 0, retries = 10; + struct dpaa2_dev_priv *priv; + struct fsl_mc_io *dpni; + + PMD_INIT_FUNC_TRACE(); + + priv = dev->data->dev_private; + dpni = dev->process_private; + + if (!dpni) { + DPAA2_PMD_ERR("Device has not yet been configured"); + return -ENODEV; + } + + /*changing tx burst function to avoid any more enqueues */ + dev->tx_pkt_burst = rte_eth_pkt_burst_dummy; + + /* Loop while dpni_disable() attempts to drain the egress FQs + * and confirm them back to us. + */ + do { + ret = dpni_disable(dpni, 0, priv->token); + if (ret) { + DPAA2_PMD_ERR("dpni disable failed (%d)", ret); + return ret; + } + ret = dpni_is_enabled(dpni, 0, priv->token, &dpni_enabled); + if (ret) { + DPAA2_PMD_ERR("dpni enable check failed (%d)", ret); + return ret; + } + if (dpni_enabled) + /* Allow the MC some slack */ + rte_delay_ms(CHECK_INTERVAL); + } while (dpni_enabled && --retries); + + if (!retries) { + DPAA2_PMD_WARN("Retry count exceeded disabling dpni"); + /* todo- we may have to manually cleanup queues. + */ + } else { + DPAA2_PMD_INFO("Port %d Link DOWN successful", dev->data->port_id); + } + + dev->data->dev_link.link_status = 0; + + return ret; +} + /** * Dpaa2 link Interrupt handler * @@ -1842,19 +2059,18 @@ dpaa2_eth_setup_irqs(struct rte_eth_dev *dev, int enable) PMD_INIT_FUNC_TRACE(); - err = dpni_set_irq_mask(dpni, CMD_PRI_LOW, priv->token, - irq_index, mask); + err = dpni_set_irq_mask(dpni, CMD_PRI_LOW, priv->token, irq_index, mask); if (err < 0) { DPAA2_PMD_ERR("Error: dpni_set_irq_mask():%d (%s)", err, - strerror(-err)); + strerror(-err)); return err; } - err = dpni_set_irq_enable(dpni, CMD_PRI_LOW, priv->token, - irq_index, enable); - if (err < 0) + err = dpni_set_irq_enable(dpni, CMD_PRI_LOW, priv->token, irq_index, enable); + if (err < 0) { DPAA2_PMD_ERR("Error: dpni_set_irq_enable():%d (%s)", err, - strerror(-err)); + strerror(-err)); + } return err; } @@ -2021,8 +2237,7 @@ dpaa2_dev_stop(struct rte_eth_dev *dev) /* Unregistering LSC interrupt handler */ rte_intr_callback_unregister(intr_handle, - dpaa2_interrupt_handler, - (void *)dev); + dpaa2_interrupt_handler, (void *)dev); } dpaa2_dev_set_link_down(dev); @@ -2233,14 +2448,14 @@ dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) if (!dpni) { DPAA2_PMD_ERR("dpni is NULL"); - return -EINVAL; + return -ENODEV; } /* Set the Max Rx frame length as 'mtu' + * Maximum Ethernet header length */ ret = dpni_set_max_frame_length(dpni, CMD_PRI_LOW, priv->token, - frame_size - RTE_ETHER_CRC_LEN); + frame_size - RTE_ETHER_CRC_LEN); if (ret) { DPAA2_PMD_ERR("Setting the max frame length failed"); return ret; @@ -2676,175 +2891,6 @@ dpaa2_dev_stats_reset(struct rte_eth_dev *dev) return retcode; }; -/* return 0 means link status changed, -1 means not changed */ -static int -dpaa2_dev_link_update(struct rte_eth_dev *dev, - int wait_to_complete) -{ - int ret; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - struct fsl_mc_io *dpni = dev->process_private; - struct rte_eth_link link; - struct dpni_link_state state = {0}; - uint8_t count; - - if (!dpni) { - DPAA2_PMD_ERR("dpni is NULL"); - return 0; - } - - for (count = 0; count <= MAX_REPEAT_TIME; count++) { - ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, - &state); - if (ret < 0) { - DPAA2_PMD_DEBUG("error: dpni_get_link_state %d", ret); - return ret; - } - if (state.up == RTE_ETH_LINK_DOWN && - wait_to_complete) - rte_delay_ms(CHECK_INTERVAL); - else - break; - } - - memset(&link, 0, sizeof(struct rte_eth_link)); - link.link_status = state.up; - link.link_speed = state.rate; - - if (state.options & DPNI_LINK_OPT_HALF_DUPLEX) - link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX; - else - link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; - - ret = rte_eth_linkstatus_set(dev, &link); - if (ret < 0) - DPAA2_PMD_DEBUG("No change in status"); - else - DPAA2_PMD_INFO("Port %d Link is %s", dev->data->port_id, - link.link_status ? "Up" : "Down"); - - return ret; -} - -/** - * Toggle the DPNI to enable, if not already enabled. - * This is not strictly PHY up/down - it is more of logical toggling. - */ -static int -dpaa2_dev_set_link_up(struct rte_eth_dev *dev) -{ - int ret = -EINVAL; - struct dpaa2_dev_priv *priv; - struct fsl_mc_io *dpni; - int en = 0; - struct dpni_link_state state = {0}; - - priv = dev->data->dev_private; - dpni = dev->process_private; - - if (!dpni) { - DPAA2_PMD_ERR("dpni is NULL"); - return ret; - } - - /* Check if DPNI is currently enabled */ - ret = dpni_is_enabled(dpni, CMD_PRI_LOW, priv->token, &en); - if (ret) { - /* Unable to obtain dpni status; Not continuing */ - DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret); - return ret; - } - - /* Enable link if not already enabled */ - if (!en) { - ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token); - if (ret) { - DPAA2_PMD_ERR("Interface Link UP failed (%d)", ret); - return ret; - } - } - ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state); - if (ret < 0) { - DPAA2_PMD_DEBUG("Unable to get link state (%d)", ret); - return ret; - } - - /* changing tx burst function to start enqueues */ - dev->tx_pkt_burst = dpaa2_dev_tx; - dev->data->dev_link.link_status = state.up; - dev->data->dev_link.link_speed = state.rate; - - if (state.options & DPNI_LINK_OPT_HALF_DUPLEX) - dev->data->dev_link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX; - else - dev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX; - - if (state.up) - DPAA2_PMD_DEBUG("Port %d Link is Up", dev->data->port_id); - else - DPAA2_PMD_DEBUG("Port %d Link is Down", dev->data->port_id); - return ret; -} - -/** - * Toggle the DPNI to disable, if not already disabled. - * This is not strictly PHY up/down - it is more of logical toggling. - */ -static int -dpaa2_dev_set_link_down(struct rte_eth_dev *dev) -{ - int ret = -EINVAL; - struct dpaa2_dev_priv *priv; - struct fsl_mc_io *dpni; - int dpni_enabled = 0; - int retries = 10; - - PMD_INIT_FUNC_TRACE(); - - priv = dev->data->dev_private; - dpni = dev->process_private; - - if (!dpni) { - DPAA2_PMD_ERR("Device has not yet been configured"); - return ret; - } - - /*changing tx burst function to avoid any more enqueues */ - dev->tx_pkt_burst = rte_eth_pkt_burst_dummy; - - /* Loop while dpni_disable() attempts to drain the egress FQs - * and confirm them back to us. - */ - do { - ret = dpni_disable(dpni, 0, priv->token); - if (ret) { - DPAA2_PMD_ERR("dpni disable failed (%d)", ret); - return ret; - } - ret = dpni_is_enabled(dpni, 0, priv->token, &dpni_enabled); - if (ret) { - DPAA2_PMD_ERR("dpni enable check failed (%d)", ret); - return ret; - } - if (dpni_enabled) - /* Allow the MC some slack */ - rte_delay_ms(CHECK_INTERVAL); - } while (dpni_enabled && --retries); - - if (!retries) { - DPAA2_PMD_WARN("Retry count exceeded disabling dpni"); - /* todo- we may have to manually cleanup queues. - */ - } else { - DPAA2_PMD_INFO("Port %d Link DOWN successful", - dev->data->port_id); - } - - dev->data->dev_link.link_status = 0; - - return ret; -} - static int dpaa2_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 27/65] net/dpaa2: support DCB Rx mode via rte_flow 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (25 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 26/65] net/dpaa2: program flow table miss actions via rte_flow Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 28/65] net/dpaa2: reject Rx queue deferred start Prashant Gupta ` (37 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add DCB (Data Center Bridging) support to the DPAA2 PMD so that applications requesting RTE_ETH_MQ_RX_DCB map VLAN PCP priorities to receive TCs, and expose the per-port mapping through the standard rte_eth_dev_get_dcb_info() API. Reject QoS entries whose index collides with an already-installed DCB flow slot with -ENODATA, so user-added QoS rules cannot silently overwrite the DCB-generated ones. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 107 ++++++++++++++++++++++++++++--- drivers/net/dpaa2/dpaa2_ethdev.h | 3 + drivers/net/dpaa2/dpaa2_flow.c | 5 ++ 3 files changed, 105 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 9f92789d4e..cca7aa0891 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -507,7 +507,7 @@ dpaa2_setup_table_miss_action(struct rte_eth_dev *eth_dev, } static int -dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, +dpaa2_setup_flow_rss_dist(struct rte_eth_dev *eth_dev, uint64_t req_dist_set, int tc_index) { struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; @@ -555,6 +555,49 @@ dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev, return 0; } +static int +dpaa2_setup_flow_dcb_dist(struct rte_eth_dev *eth_dev, + uint8_t prio, uint8_t tc) +{ + struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; + struct rte_flow_attr attr; + struct rte_flow_action actions[2]; + struct rte_flow_item_vlan vlan_item; + struct rte_flow_item_vlan vlan_mask; + struct rte_flow_item items[2]; + struct rte_flow_action_jump action_jump; + struct rte_flow *qos_flow; + + memset(&attr, 0, sizeof(struct rte_flow_attr)); + attr.ingress = 1; + + attr.group = priv->num_rx_tc; + attr.priority = prio; + memset(&vlan_item, 0, sizeof(struct rte_flow_item_vlan)); + memset(&vlan_mask, 0, sizeof(struct rte_flow_item_vlan)); + vlan_item.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_TCI_MAKE(0, prio, 0)); + vlan_mask.hdr.vlan_tci = rte_cpu_to_be_16(RTE_VLAN_PRI_MASK); + items[0].spec = &vlan_item; + items[0].mask = &vlan_mask; + items[0].type = RTE_FLOW_ITEM_TYPE_VLAN; + items[1].type = RTE_FLOW_ITEM_TYPE_END; + + actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; + action_jump.group = tc; + actions[0].conf = &action_jump; + actions[1].type = RTE_FLOW_ACTION_TYPE_END; + + qos_flow = rte_flow_create(eth_dev->data->port_id, + &attr, items, actions, NULL); + if (!qos_flow) { + DPAA2_PMD_WARN("Failed to direct vlan with prio(%d) to tc%d", prio, tc); + return -EIO; + } + priv->dcb_flow[prio] = qos_flow; + + return 0; +} + static int dpaa2_remove_flow_rss_dist(struct rte_eth_dev *eth_dev, uint8_t tc_index) @@ -1175,6 +1218,28 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) } } +static int +dpaa2_dev_dcb_info(struct rte_eth_dev *dev, + struct rte_eth_dcb_info *dcb_info) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + int i; + + if (!priv->nb_dcb_tcs) + return -ENOTSUP; + + memset(dcb_info, 0, sizeof(struct rte_eth_dcb_info)); + dcb_info->nb_tcs = priv->nb_dcb_tcs; + rte_memcpy(dcb_info->prio_tc, priv->prio_dcb_tc, + sizeof(uint8_t) * RTE_ETH_DCB_NUM_USER_PRIORITIES); + for (i = 0; i < dcb_info->nb_tcs; i++) { + dcb_info->tc_queue.tc_rxq[0][i].base = priv->dist_queues * i; + dcb_info->tc_queue.tc_rxq[0][i].nb_queue = priv->dist_queues; + } + + return 0; +} + static int dpaa2_eth_dev_configure(struct rte_eth_dev *dev) { @@ -1187,7 +1252,7 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) int rx_l4_csum_offload = false; int tx_l3_csum_offload = false; int tx_l4_csum_offload = false; - int ret, tc_index; + int ret, tc_index, nb_tcs; uint32_t max_rx_pktlen; PMD_INIT_FUNC_TRACE(); @@ -1245,15 +1310,26 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) ret, dev->data->name); } - if (eth_conf->rxmode.mq_mode == RTE_ETH_MQ_RX_RSS) { + if (eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_RSS) { for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { - ret = dpaa2_setup_flow_dist(dev, - eth_conf->rx_adv_conf.rss_conf.rss_hf, - tc_index); + ret = dpaa2_setup_flow_rss_dist(dev, + eth_conf->rx_adv_conf.rss_conf.rss_hf, tc_index); if (ret) { - DPAA2_PMD_ERR( - "Unable to set flow distribution on tc%d." - "Check queue config", tc_index); + DPAA2_PMD_ERR("RSS dist on tc%d err(%d)", tc_index, ret); + return ret; + } + } + } + + if ((eth_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_DCB) && priv->qos_entries) { + nb_tcs = eth_conf->rx_adv_conf.dcb_rx_conf.nb_tcs; + for (tc_index = 0; tc_index < nb_tcs; tc_index++) { + if (tc_index >= priv->num_rx_tc) + break; + ret = dpaa2_setup_flow_dcb_dist(dev, + eth_conf->rx_adv_conf.dcb_rx_conf.dcb_tc[tc_index], tc_index); + if (ret) { + DPAA2_PMD_ERR("DCB direct to tc%d err(%d)", tc_index, ret); return ret; } } @@ -1320,7 +1396,7 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) */ if (dpaa2_svr_family == SVR_LX2160A) { ret = dpni_set_offload(dpni, CMD_PRI_LOW, priv->token, - DPNI_FLCTYPE_HASH, true); + DPNI_FLCTYPE_HASH, true); if (ret) { DPAA2_PMD_ERR("Error setting FLCTYPE: Err = %d", ret); return ret; @@ -2282,6 +2358,8 @@ dpaa2_dev_close(struct rte_eth_dev *dev) dpaa2_tm_deinit(dev); dpaa2_flow_clean(dev, MAX_TCS, DPAA2_FLOW_ALL_TYPE); + /** No matter dcb flows are created or not, they are destroyed in flow clean.*/ + memset(priv->dcb_flow, 0, sizeof(void *) * RTE_ETH_DCB_NUM_USER_PRIORITIES); /* Clean the device first */ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); if (ret) { @@ -3725,6 +3803,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, .mtr_ops_get = dpaa2_mtr_ops_get, + .get_dcb_info = dpaa2_dev_dcb_info, .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, .timesync_read_time = dpaa2_timesync_read_time, @@ -4054,6 +4133,14 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) tbl_profile->entry_map_size = entry_num / 8 + 1; } + for (i = 0; i < priv->num_rx_tc; i++) { + if (i >= RTE_ETH_DCB_NUM_USER_PRIORITIES) + break; + if (i >= priv->qos_entries) + break; + priv->prio_dcb_tc[i] = i; + } + priv->nb_dcb_tcs = i; ret = dpni_set_max_frame_length(dpni_dev, CMD_PRI_LOW, priv->token, RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN + VLAN_TAG_SIZE); if (ret) { diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 0ad237a5cc..9ef6ee0e8c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,9 @@ struct dpaa2_dev_priv { char ep_name[RTE_DEV_NAME_MAX_LEN]; struct dpaa2_flow_profile flow_profile; + uint8_t nb_dcb_tcs; + uint8_t prio_dcb_tc[RTE_ETH_DCB_NUM_USER_PRIORITIES]; + void *dcb_flow[RTE_ETH_DCB_NUM_USER_PRIORITIES]; uint16_t ss_offset; uint64_t ss_iova; diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 920e9edc51..d9f7391faf 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -3228,6 +3228,11 @@ dpaa2_flow_get_flow_index(struct dpaa2_dev_priv *priv, DPAA2_PMD_ERR("QoS flow index(%d) >= max(%d)", idx, priv->qos_entries); return -ENOSPC; } + + if (idx < RTE_ETH_DCB_NUM_USER_PRIORITIES && priv->dcb_flow[idx]) { + DPAA2_PMD_ERR("QoS flow[%d] added conflicts with dcb flow", idx); + return -ENODATA; + } } else { if (attr->priority >= priv->fs_entries) { DPAA2_PMD_ERR("FS[%d].entry(%d) >= max(%d)", -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 28/65] net/dpaa2: reject Rx queue deferred start 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (26 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 27/65] net/dpaa2: support DCB Rx mode " Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 29/65] bus/fslmc: support DPCI peer and dynamic queues Prashant Gupta ` (36 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The driver has no way to hold an Rx queue down while the port is started, and dpaa2_rxq_info_get() already reports rx_deferred_start as 0. The Tx side rejects the request; do the same for Rx instead of silently accepting a configuration that will not be honoured. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index cca7aa0891..9002556b91 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1483,6 +1483,13 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, DPAA2_PMD_DEBUG("dev =%p, queue =%d, pool = %p, conf =%p", dev, rx_queue_id, mb_pool, rx_conf); + /* Rx deferred start is not supported */ + if (rx_conf->rx_deferred_start) { + DPAA2_PMD_ERR("%s: Rx deferred start not supported", + dev->data->name); + return -EINVAL; + } + total_nb_rx_desc += nb_rx_desc; if (total_nb_rx_desc > MAX_NB_RX_DESC_IN_PEB && (priv->options & DPNI_OPT_V1_PFDR_IN_PEB)) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 29/65] bus/fslmc: support DPCI peer and dynamic queues 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (27 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 28/65] net/dpaa2: reject Rx queue deferred start Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 30/65] bus/fslmc: add alloc/free DPIO API for non-affine portals Prashant Gupta ` (35 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add dpci_get_peer_attributes() to query the DPCI object a given DPCI is connected to, and use it to fix the DPCI Tx fqid. A DPCI's Tx fqid only equals its Rx fqid when the DPCI is self-connected; when it has a real peer, the Tx fqids must come from dpci_get_tx_queue(). Rework DPCI device creation accordingly: - Replace the fixed DPAA2_DPCI_MAX_QUEUES arrays with dynamically allocated rx_queue/tx_queue arrays sized from the object's own num_of_priorities and the peer's num_of_priorities. - Determine the peer via dpci_get_peer_attributes(); fall back to self-connection when no peer is present. - Use rte_zmalloc for the node, zero the attribute structs, and replace the single err label with staged open_err/queue_err/ enable_err cleanup that closes/disables and frees only what was allocated. - Rename the internal create/close callbacks to the dpaa2_ prefix. Add rte_dpaa2_dpci_link_attach() so a consumer can bind a free DPCI Rx queue to a destination (e.g. a DPCON), install its dequeue callback and obtain the matching peer Tx queue. The event PMD uses this in place of its private dpaa2_eventdev_setup_dpci(): each event queue now tracks a per-sched-type Tx queue array (dpci_txqs[]) and the owning event port, and the enqueue path selects the Tx fqid by event->queue_id and sched_type while validating port ownership. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/mc/dpci.c | 37 +++- drivers/bus/fslmc/mc/fsl_dpci.h | 12 +- drivers/bus/fslmc/portal/dpaa2_hw_dpci.c | 225 ++++++++++++++++------- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 16 +- drivers/event/dpaa2/dpaa2_eventdev.c | 122 ++++++------ drivers/event/dpaa2/dpaa2_eventdev.h | 8 +- 6 files changed, 282 insertions(+), 138 deletions(-) diff --git a/drivers/bus/fslmc/mc/dpci.c b/drivers/bus/fslmc/mc/dpci.c index 4188325fb9..1588ba04c4 100644 --- a/drivers/bus/fslmc/mc/dpci.c +++ b/drivers/bus/fslmc/mc/dpci.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2017-2019 NXP + * Copyright 2017-2019, 2026 NXP * */ #include <fsl_mc_sys.h> @@ -304,6 +304,41 @@ int dpci_get_attributes(struct fsl_mc_io *mc_io, return 0; } +/** + * dpci_get_peer_attributes() - Retrieve DPCI peer attributes. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPCI object + * @attr: Returned DPCI peer's attributes + * + * Return: '0' on Success; Error code otherwise. + */ +int dpci_get_peer_attributes(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + struct dpci_peer_attr *attr) +{ + struct dpci_rsp_get_attr *rsp_params; + struct mc_command cmd = { 0 }; + int err; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_PEER_ATTR, + cmd_flags, token); + + /* send command to mc*/ + err = mc_send_command(mc_io, &cmd); + if (err) + return err; + + /* retrieve response parameters */ + rsp_params = (struct dpci_rsp_get_attr *)cmd.params; + attr->peer_id = le32_to_cpu(rsp_params->id); + attr->num_of_priorities = rsp_params->num_of_priorities; + + return 0; +} + /** * dpci_set_rx_queue() - Set Rx queue configuration * @mc_io: Pointer to MC portal's I/O object diff --git a/drivers/bus/fslmc/mc/fsl_dpci.h b/drivers/bus/fslmc/mc/fsl_dpci.h index 55b67244c1..a1fb747011 100644 --- a/drivers/bus/fslmc/mc/fsl_dpci.h +++ b/drivers/bus/fslmc/mc/fsl_dpci.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2013-2016 Freescale Semiconductor Inc. - * Copyright 2017-2019 NXP + * Copyright 2017-2019, 2026 NXP * */ #ifndef __FSL_DPCI_H @@ -111,6 +111,16 @@ int dpci_get_attributes(struct fsl_mc_io *mc_io, uint16_t token, struct dpci_attr *attr); +struct dpci_peer_attr { + int peer_id; + uint8_t num_of_priorities; +}; + +int dpci_get_peer_attributes(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + struct dpci_peer_attr *attr); + /** * enum dpci_dest - DPCI destination types * @DPCI_DEST_NONE: Unassigned destination; The queue is set in parked mode diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c index 20371fe062..f2bfb2a75c 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2017, 2020, 2023 NXP + * Copyright 2017, 2020, 2023, 2026 NXP * */ @@ -45,19 +45,23 @@ static struct dpaa2_dpci_dev *get_dpci_from_id(uint32_t dpci_id) } static int -rte_dpaa2_create_dpci_device(int vdev_fd __rte_unused, +dpaa2_create_dpci_device(int vdev_fd __rte_unused, struct vfio_device_info *obj_info __rte_unused, struct rte_dpaa2_device *obj) { struct dpaa2_dpci_dev *dpci_node; struct dpci_attr attr; + struct dpci_peer_attr peer_attr; struct dpci_rx_queue_cfg rx_queue_cfg; struct dpci_rx_queue_attr rx_attr; struct dpci_tx_queue_attr tx_attr; int ret, i, dpci_id = obj->object_id; + memset(&attr, 0, sizeof(struct dpci_attr)); + memset(&peer_attr, 0, sizeof(struct dpci_peer_attr)); + /* Allocate DPAA2 dpci handle */ - dpci_node = rte_malloc(NULL, sizeof(struct dpaa2_dpci_dev), 0); + dpci_node = rte_zmalloc(NULL, sizeof(struct dpaa2_dpci_dev), 0); if (!dpci_node) { DPAA2_BUS_ERR("Memory allocation failed for DPCI Device"); return -ENOMEM; @@ -65,88 +69,119 @@ rte_dpaa2_create_dpci_device(int vdev_fd __rte_unused, /* Open the dpci object */ dpci_node->dpci.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); - ret = dpci_open(&dpci_node->dpci, - CMD_PRI_LOW, dpci_id, &dpci_node->token); + ret = dpci_open(&dpci_node->dpci, CMD_PRI_LOW, dpci_id, &dpci_node->token); if (ret) { DPAA2_BUS_ERR("Resource alloc failure with err code: %d", ret); - goto err; + goto open_err; } /* Get the device attributes */ ret = dpci_get_attributes(&dpci_node->dpci, - CMD_PRI_LOW, dpci_node->token, &attr); - if (ret != 0) { + CMD_PRI_LOW, dpci_node->token, &attr); + if (ret) { DPAA2_BUS_ERR("Reading device failed with err code: %d", ret); - goto err; + goto open_err; + } else { + if (dpci_id != attr.id) { + ret = -EINVAL; + goto open_err; + } + dpci_node->dpci_id = attr.id; + dpci_node->rx_queue_num = attr.num_of_priorities; } - for (i = 0; i < DPAA2_DPCI_MAX_QUEUES; i++) { - struct dpaa2_queue *rxq; + if (dpci_node->rx_queue_num) { + dpci_node->rx_queue = rte_zmalloc(NULL, + sizeof(struct dpaa2_queue) * dpci_node->rx_queue_num, 0); + if (!dpci_node->rx_queue) { + DPAA2_BUS_ERR("DPCI.%d alloc rxq failed!", dpci_id); + ret = -ENOMEM; + goto open_err; + } + } + for (i = 0; i < dpci_node->rx_queue_num; i++) { memset(&rx_queue_cfg, 0, sizeof(struct dpci_rx_queue_cfg)); - ret = dpci_set_rx_queue(&dpci_node->dpci, - CMD_PRI_LOW, - dpci_node->token, - i, &rx_queue_cfg); + rx_queue_cfg.user_ctx = (uint64_t)&dpci_node->rx_queue[i]; + rx_queue_cfg.dest_cfg.dest_type = DPCI_DEST_NONE; + ret = dpci_set_rx_queue(&dpci_node->dpci, CMD_PRI_LOW, + dpci_node->token, i, &rx_queue_cfg); if (ret) { - DPAA2_BUS_ERR("Setting Rx queue failed with err code: %d", - ret); - goto err; + DPAA2_BUS_ERR("Setting Rx queue failed with err code: %d", ret); + goto queue_err; } - /* Allocate DQ storage for the DPCI Rx queues */ - rxq = &dpci_node->rx_queue[i]; - ret = dpaa2_queue_storage_alloc(rxq, 1); - if (ret) - goto err; + ret = dpci_get_rx_queue(&dpci_node->dpci, CMD_PRI_LOW, + dpci_node->token, i, &rx_attr); + if (ret) { + DPAA2_BUS_ERR("Rx queue fetch failed with err code: %d", ret); + goto queue_err; + } + dpci_node->rx_queue[i].fqid = rx_attr.fqid; } /* Enable the device */ - ret = dpci_enable(&dpci_node->dpci, - CMD_PRI_LOW, dpci_node->token); - if (ret != 0) { + ret = dpci_enable(&dpci_node->dpci, CMD_PRI_LOW, dpci_node->token); + if (ret) { DPAA2_BUS_ERR("Enabling device failed with err code: %d", ret); - goto err; - } - - for (i = 0; i < DPAA2_DPCI_MAX_QUEUES; i++) { - /* Get the Rx FQID's */ - ret = dpci_get_rx_queue(&dpci_node->dpci, - CMD_PRI_LOW, - dpci_node->token, i, - &rx_attr); - if (ret != 0) { - DPAA2_BUS_ERR("Rx queue fetch failed with err code: %d", - ret); - goto err; + goto enable_err; + } + + ret = dpci_get_peer_attributes(&dpci_node->dpci, + CMD_PRI_LOW, dpci_node->token, &peer_attr); + if (ret) { + DPAA2_BUS_ERR("Getting peer failed with err code: %d", ret); + goto enable_err; + } else if (peer_attr.peer_id < 0) { + DPAA2_BUS_INFO("DPCI.%d has no peer, self connected.", dpci_node->dpci_id); + /** Connect to self.*/ + dpci_node->peer_id = dpci_node->dpci_id; + dpci_node->tx_queue_num = dpci_node->rx_queue_num; + } else { + dpci_node->peer_id = peer_attr.peer_id; + dpci_node->tx_queue_num = peer_attr.num_of_priorities; + } + + if (dpci_node->tx_queue_num) { + dpci_node->tx_queue = rte_zmalloc(NULL, + sizeof(struct dpaa2_queue) * dpci_node->tx_queue_num, 0); + if (!dpci_node->tx_queue) { + DPAA2_BUS_ERR("DPCI.%d alloc txq failed!", dpci_id); + ret = -ENOMEM; + goto enable_err; } - dpci_node->rx_queue[i].fqid = rx_attr.fqid; + } - ret = dpci_get_tx_queue(&dpci_node->dpci, - CMD_PRI_LOW, - dpci_node->token, i, - &tx_attr); - if (ret != 0) { - DPAA2_BUS_ERR("Reading device failed with err code: %d", - ret); - goto err; + for (i = 0; i < dpci_node->tx_queue_num; i++) { + if (dpci_node->peer_id != dpci_node->dpci_id) { + ret = dpci_get_tx_queue(&dpci_node->dpci, CMD_PRI_LOW, + dpci_node->token, i, &tx_attr); + if (ret) { + DPAA2_BUS_ERR("Tx queue fetch failed with err code: %d", ret); + goto enable_err; + } + dpci_node->tx_queue[i].fqid = tx_attr.fqid; + } else { + dpci_node->tx_queue[i].fqid = dpci_node->rx_queue[i].fqid; } - dpci_node->tx_queue[i].fqid = tx_attr.fqid; } - dpci_node->dpci_id = dpci_id; rte_atomic_store_explicit(&dpci_node->in_use, 0, rte_memory_order_relaxed); TAILQ_INSERT_TAIL(&dpci_dev_list, dpci_node, next); return 0; -err: - for (i = 0; i < DPAA2_DPCI_MAX_QUEUES; i++) { - struct dpaa2_queue *rxq = &dpci_node->rx_queue[i]; +enable_err: + if (dpci_node->tx_queue) + rte_free(dpci_node->tx_queue); + dpci_disable(&dpci_node->dpci, CMD_PRI_LOW, dpci_node->token); +queue_err: + if (dpci_node->rx_queue) + rte_free(dpci_node->rx_queue); +open_err: + dpci_close(&dpci_node->dpci, CMD_PRI_LOW, dpci_node->token); - dpaa2_queue_storage_free(rxq, 1); - } rte_free(dpci_node); return ret; @@ -156,14 +191,13 @@ RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_alloc_dpci_dev) struct dpaa2_dpci_dev *rte_dpaa2_alloc_dpci_dev(void) { struct dpaa2_dpci_dev *dpci_dev = NULL; + uint16_t expected = 0; /* Get DPCI dev handle from list using index */ TAILQ_FOREACH(dpci_dev, &dpci_dev_list, next) { - uint16_t expected = 0; - - if (rte_atomic_compare_exchange_strong_explicit(&dpci_dev->in_use, - &expected, 1, rte_memory_order_acquire, - rte_memory_order_relaxed)) + if (dpci_dev && + rte_atomic_compare_exchange_strong_explicit(&dpci_dev->in_use, + &expected, 1, rte_memory_order_acquire, rte_memory_order_relaxed)) break; } @@ -178,33 +212,90 @@ void rte_dpaa2_free_dpci_dev(struct dpaa2_dpci_dev *dpci) /* Match DPCI handle and mark it free */ TAILQ_FOREACH(dpci_dev, &dpci_dev_list, next) { if (dpci_dev == dpci) { - rte_atomic_store_explicit(&dpci_dev->in_use, 0, - rte_memory_order_release); + rte_atomic_fetch_sub_explicit(&dpci_dev->in_use, 1, + rte_memory_order_acq_rel); return; } } } - static void -rte_dpaa2_close_dpci_device(int object_id) +dpaa2_close_dpci_device(int object_id) { struct dpaa2_dpci_dev *dpci_dev = NULL; dpci_dev = get_dpci_from_id((uint32_t)object_id); if (dpci_dev) { - rte_dpaa2_free_dpci_dev(dpci_dev); + dpci_disable(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token); + rte_free(dpci_dev->rx_queue); + rte_free(dpci_dev->tx_queue); dpci_close(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token); TAILQ_REMOVE(&dpci_dev_list, dpci_dev, next); rte_free(dpci_dev); } } +RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_dpci_link_attach) +int +rte_dpaa2_dpci_link_attach(struct dpaa2_dpci_dev *dpci_dev, + enum dpci_dest dest_type, uint32_t dest_id, uint8_t priority, + dpaa2_queue_cb_dqrr_t *rx_cb, struct dpaa2_queue **txq) +{ + struct dpci_rx_queue_cfg rx_queue_cfg; + uint16_t i; + int ret; + struct dpaa2_dpci_dev *peer_dpci; + + memset(&rx_queue_cfg, 0, sizeof(struct dpci_rx_queue_cfg)); + if (dpci_dev->dpci_id == dpci_dev->peer_id) { + peer_dpci = dpci_dev; + } else { + peer_dpci = get_dpci_from_id(dpci_dev->peer_id); + if (!peer_dpci) { + DPAA2_BUS_ERR("Get peer of DPCI.%d failed", + dpci_dev->dpci_id); + return -ENODEV; + } + } + + /*Do settings to get the frame on a DPCON object*/ + rx_queue_cfg.options = DPCI_QUEUE_OPT_DEST | + DPCI_QUEUE_OPT_USER_CTX; + rx_queue_cfg.dest_cfg.dest_type = dest_type; + rx_queue_cfg.dest_cfg.dest_id = dest_id; + rx_queue_cfg.dest_cfg.priority = priority; + rx_queue_cfg.order_preservation_en = 0; + + for (i = 0; i < dpci_dev->rx_queue_num; i++) { + if (!dpci_dev->rx_queue[i].cb) + break; + } + if (i >= dpci_dev->rx_queue_num || i >= dpci_dev->tx_queue_num) { + DPAA2_BUS_ERR("DPCI.%d No queue pair available!", dpci_dev->dpci_id); + return -EBUSY; + } + + rx_queue_cfg.user_ctx = (uint64_t)(&dpci_dev->rx_queue[i]); + ret = dpci_set_rx_queue(&dpci_dev->dpci, CMD_PRI_LOW, + dpci_dev->token, i, &rx_queue_cfg); + if (ret) { + DPAA2_BUS_ERR("DPCI.%d Rx queue%d setup failed: err(%d)", + dpci_dev->dpci_id, i, ret); + return ret; + } + dpci_dev->rx_queue[i].cb = rx_cb; + + if (txq) + *txq = &dpci_dev->tx_queue[i]; + + return 0; +} + static struct rte_dpaa2_object rte_dpaa2_dpci_obj = { .dev_type = DPAA2_CI, - .create = rte_dpaa2_create_dpci_device, - .close = rte_dpaa2_close_dpci_device, + .create = dpaa2_create_dpci_device, + .close = dpaa2_close_dpci_device, }; RTE_PMD_REGISTER_DPAA2_OBJECT(dpci, rte_dpaa2_dpci_obj); diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 9dba5dbbd1..ed82eb123a 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -14,6 +14,7 @@ #include <dpaax_iova_table.h> #include <mc/fsl_mc_sys.h> +#include <mc/fsl_dpci.h> #include <fsl_qbman_portal.h> #include <bus_fslmc_driver.h> @@ -81,7 +82,6 @@ #define DPAA2_HW_BUF_RESERVE 0 #define DPAA2_PACKET_LAYOUT_ALIGN 64 /*changing from 256 */ -#define DPAA2_DPCI_MAX_QUEUES 2 #define DPAA2_INVALID_FLOW_ID 0xffff #define DPAA2_INVALID_FQ_ID ((uint32_t)(-1)) #define DPAA2_INVALID_CGID 0xff @@ -267,13 +267,16 @@ struct dpaa2_dprc_dev { struct dpaa2_dpci_dev { TAILQ_ENTRY(dpaa2_dpci_dev) next; - /**< Pointer to Next device instance */ + /**< Pointer to Next device instance */ struct fsl_mc_io dpci; /** handle to DPCI portal object */ uint16_t token; RTE_ATOMIC(uint16_t) in_use; uint32_t dpci_id; /*HW ID for DPCI object */ - struct dpaa2_queue rx_queue[DPAA2_DPCI_MAX_QUEUES]; - struct dpaa2_queue tx_queue[DPAA2_DPCI_MAX_QUEUES]; + uint32_t peer_id; + uint16_t rx_queue_num; + uint16_t tx_queue_num; + struct dpaa2_queue *rx_queue; + struct dpaa2_queue *tx_queue; }; struct dpaa2_dpcon_dev { @@ -577,6 +580,11 @@ struct dpaa2_dpci_dev *rte_dpaa2_alloc_dpci_dev(void); __rte_internal void rte_dpaa2_free_dpci_dev(struct dpaa2_dpci_dev *dpci); +__rte_internal +int rte_dpaa2_dpci_link_attach(struct dpaa2_dpci_dev *dpci_dev, + enum dpci_dest dest_type, uint32_t dest_id, uint8_t priority, + dpaa2_queue_cb_dqrr_t *rx_cb, struct dpaa2_queue **txq); + /* Global MCP pointer */ __rte_internal void *dpaa2_get_mcp_ptr(int portal_idx); diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index ddcf7b3678..28ed07bd97 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -55,12 +55,12 @@ static uint16_t dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], uint16_t nb_events) { - struct dpaa2_port *dpaa2_portal = port; struct dpaa2_dpio_dev *dpio_dev; - uint32_t queue_id = ev[0].queue_id; + struct rte_eventdev *eventdev = dpaa2_portal->eventdev; + struct dpaa2_eventdev *priv = eventdev->data->dev_private; struct dpaa2_eventq *evq_info; - uint32_t fqid, retry_count; + uint32_t queue_id, retry_count; struct qbman_swp *swp; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t loop, frames_to_send; @@ -68,6 +68,8 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], uint16_t num_tx = 0; int i, n, ret; uint8_t channel_index; + const struct rte_event *event; + struct dpaa2_queue *dpci_txq; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { /* Affine current thread context to a qman portal */ @@ -109,25 +111,33 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], dpaa2_portal->is_port_linked = true; skip_linking: - evq_info = &dpaa2_portal->evq_info[queue_id]; - while (nb_events) { frames_to_send = (nb_events > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_events; for (loop = 0; loop < frames_to_send; loop++) { - const struct rte_event *event = &ev[num_tx + loop]; - - if (event->sched_type != RTE_SCHED_TYPE_ATOMIC) - fqid = evq_info->dpci->rx_queue[ - DPAA2_EVENT_DPCI_PARALLEL_QUEUE].fqid; - else - fqid = evq_info->dpci->rx_queue[ - DPAA2_EVENT_DPCI_ATOMIC_QUEUE].fqid; + event = &ev[num_tx + loop]; + queue_id = event->queue_id; + if (unlikely(queue_id >= DPAA2_EVENT_MAX_QUEUES || + priv->evq_info[queue_id].event_port != dpaa2_portal)) { + DPAA2_EVENTDEV_ERR("Event queue%d is not handled by port%d", + queue_id, dpaa2_portal->port_id); + ret = -EINVAL; + goto send_partial; + } + evq_info = &priv->evq_info[queue_id]; + if (unlikely(event->sched_type >= DPAA2_EVENTQ_LINK_CONF_MAX || + !evq_info->dpci_txqs[event->sched_type])) { + DPAA2_EVENTDEV_ERR("Event sched_type(%d) is not supported", + event->sched_type); + ret = -ENOTSUP; + goto send_partial; + } + dpci_txq = evq_info->dpci_txqs[event->sched_type]; /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); - qbman_eq_desc_set_fq(&eqdesc[loop], fqid); + qbman_eq_desc_set_fq(&eqdesc[loop], dpci_txq->fqid); qbman_eq_desc_set_no_orp(&eqdesc[loop], 0); qbman_eq_desc_set_response(&eqdesc[loop], 0, 0); @@ -401,7 +411,6 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, RTE_EVENT_DEV_CAP_BURST_MODE| RTE_EVENT_DEV_CAP_RUNTIME_PORT_LINK | RTE_EVENT_DEV_CAP_MULTIPLE_QUEUE_PORT | - RTE_EVENT_DEV_CAP_NONSEQ_MODE | RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES | RTE_EVENT_DEV_CAP_CARRY_FLOW_ID | RTE_EVENT_DEV_CAP_MAINTENANCE_FREE; @@ -498,7 +507,6 @@ dpaa2_eventdev_queue_setup(struct rte_eventdev *dev, uint8_t queue_id, switch (queue_conf->schedule_type) { case RTE_SCHED_TYPE_PARALLEL: case RTE_SCHED_TYPE_ATOMIC: - case RTE_SCHED_TYPE_ORDERED: break; default: DPAA2_EVENTDEV_ERR("Schedule type is not supported."); @@ -546,13 +554,14 @@ dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, RTE_SET_USED(port_conf); sprintf(event_port_name, "event-port-%d", port_id); - portal = rte_malloc(event_port_name, sizeof(struct dpaa2_port), 0); + portal = rte_zmalloc(event_port_name, sizeof(struct dpaa2_port), 0); if (!portal) { DPAA2_EVENTDEV_ERR("Memory allocation failure"); return -ENOMEM; } + portal->eventdev = dev; - memset(portal, 0, sizeof(struct dpaa2_port)); + portal->port_id = port_id; dev->data->ports[port_id] = portal; return 0; } @@ -1062,41 +1071,6 @@ static struct eventdev_ops dpaa2_eventdev_ops = { .crypto_adapter_stop = dpaa2_eventdev_crypto_stop, }; -static int -dpaa2_eventdev_setup_dpci(struct dpaa2_dpci_dev *dpci_dev, - struct dpaa2_dpcon_dev *dpcon_dev) -{ - struct dpci_rx_queue_cfg rx_queue_cfg; - int ret, i; - - /*Do settings to get the frame on a DPCON object*/ - rx_queue_cfg.options = DPCI_QUEUE_OPT_DEST | - DPCI_QUEUE_OPT_USER_CTX; - rx_queue_cfg.dest_cfg.dest_type = DPCI_DEST_DPCON; - rx_queue_cfg.dest_cfg.dest_id = dpcon_dev->dpcon_id; - rx_queue_cfg.dest_cfg.priority = DPAA2_EVENT_DEFAULT_DPCI_PRIO; - - dpci_dev->rx_queue[DPAA2_EVENT_DPCI_PARALLEL_QUEUE].cb = - dpaa2_eventdev_process_parallel; - dpci_dev->rx_queue[DPAA2_EVENT_DPCI_ATOMIC_QUEUE].cb = - dpaa2_eventdev_process_atomic; - - for (i = 0 ; i < DPAA2_EVENT_DPCI_MAX_QUEUES; i++) { - rx_queue_cfg.user_ctx = (size_t)(&dpci_dev->rx_queue[i]); - ret = dpci_set_rx_queue(&dpci_dev->dpci, - CMD_PRI_LOW, - dpci_dev->token, i, - &rx_queue_cfg); - if (ret) { - DPAA2_EVENTDEV_ERR( - "DPCI Rx queue setup failed: err(%d)", - ret); - return ret; - } - } - return 0; -} - static int dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) { @@ -1104,12 +1078,12 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) struct dpaa2_eventdev *priv; struct dpaa2_dpcon_dev *dpcon_dev = NULL; struct dpaa2_dpci_dev *dpci_dev = NULL; + struct dpaa2_eventq *evq_info; int ret; eventdev = rte_event_pmd_vdev_init(name, - sizeof(struct dpaa2_eventdev), - rte_socket_id(), vdev); - if (eventdev == NULL) { + sizeof(struct dpaa2_eventdev), rte_socket_id(), vdev); + if (!eventdev) { DPAA2_EVENTDEV_ERR("Failed to create Event device %s", name); goto fail; } @@ -1127,27 +1101,49 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) goto done; priv = eventdev->data->dev_private; - priv->max_event_queues = 0; + memset(priv, 0, sizeof(struct dpaa2_eventdev)); do { + evq_info = &priv->evq_info[priv->max_event_queues]; dpcon_dev = rte_dpaa2_alloc_dpcon_dev(); if (!dpcon_dev) break; - priv->evq_info[priv->max_event_queues].dpcon = dpcon_dev; + evq_info->dpcon = dpcon_dev; dpci_dev = rte_dpaa2_alloc_dpci_dev(); if (!dpci_dev) { rte_dpaa2_free_dpcon_dev(dpcon_dev); break; } - priv->evq_info[priv->max_event_queues].dpci = dpci_dev; + evq_info->dpci = dpci_dev; - ret = dpaa2_eventdev_setup_dpci(dpci_dev, dpcon_dev); + ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, + dpcon_dev->dpcon_id, 0, + dpaa2_eventdev_process_parallel, + &evq_info->dpci_txqs[RTE_SCHED_TYPE_PARALLEL]); if (ret) { - DPAA2_EVENTDEV_ERR( - "DPCI setup failed: err(%d)", ret); - return ret; + rte_dpaa2_free_dpcon_dev(evq_info->dpcon); + rte_dpaa2_free_dpci_dev(evq_info->dpci); + DPAA2_EVENTDEV_ERR("DPCI attach parallel RX failed: err(%d)", ret); + break; } + + ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, + dpcon_dev->dpcon_id, 0, + dpaa2_eventdev_process_atomic, + &evq_info->dpci_txqs[RTE_SCHED_TYPE_ATOMIC]); + if (ret) { + rte_dpaa2_free_dpcon_dev(evq_info->dpcon); + rte_dpaa2_free_dpci_dev(evq_info->dpci); + DPAA2_EVENTDEV_ERR("DPCI attach atomic RX failed: err(%d)", ret); + break; + } + + /** TO DO: order schedule.*/ + + evq_info->valid = true; + evq_info->event_port = NULL; + priv->max_event_queues++; } while (dpcon_dev && dpci_dev); diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index a054dfdbd7..9f0abae9d4 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -51,20 +51,24 @@ enum { * the ethdev to eventdev with DPAA2 devices. */ +#define DPAA2_EVENTQ_LINK_CONF_MAX 4 /** Max schedule type + 1.*/ struct dpaa2_eventq { + int valid; + void *event_port; /* DPcon device */ struct dpaa2_dpcon_dev *dpcon; /* Attached DPCI device */ struct dpaa2_dpci_dev *dpci; - /* Mapped event port */ - struct dpaa2_io_portal_t *event_port; /* Configuration provided by the user */ uint32_t event_queue_cfg; uint32_t event_queue_id; + struct dpaa2_queue *dpci_txqs[DPAA2_EVENTQ_LINK_CONF_MAX]; }; struct dpaa2_port { + struct rte_eventdev *eventdev; struct dpaa2_eventq evq_info[DPAA2_EVENT_MAX_QUEUES]; + uint8_t port_id; uint8_t num_linked_evq; uint8_t is_port_linked; uint64_t timeout_us; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 30/65] bus/fslmc: add alloc/free DPIO API for non-affine portals 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (28 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 29/65] bus/fslmc: support DPCI peer and dynamic queues Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 31/65] event/dpaa2: rework event port model and DPCI handling Prashant Gupta ` (34 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add rte_dpaa2_alloc_dpio_device() and rte_dpaa2_free_dpio_device() to grab and release a DPIO software portal that is not tied to a specific CPU affinity. The allocator reserves a free portal from the DPIO list, sets up the DQRI interrupt when the event driver is built in, and the release helper returns the portal via dpaa2_put_qbman_swp(). This lets consumers that manage their own threading (rather than the per-lcore affine portals) obtain a dedicated portal handle. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 40 ++++++++++++++++++++++++ drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 8 +++++ 2 files changed, 48 insertions(+) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 8af8600935..63e1660686 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -422,6 +422,46 @@ static void dpaa2_portal_finish(void *arg) pthread_setspecific(dpaa2_portal_key, NULL); } +RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_alloc_dpio_device) +struct dpaa2_dpio_dev * +rte_dpaa2_alloc_dpio_device(void) +{ + struct dpaa2_dpio_dev *dpio_dev = NULL; + uint16_t expected = 0; + + /* Get DPIO dev handle from list using index */ + TAILQ_FOREACH(dpio_dev, &dpio_dev_list, next) { + if (dpio_dev && + rte_atomic_compare_exchange_strong_explicit(&dpio_dev->ref_count, + &expected, 1, rte_memory_order_acquire, rte_memory_order_relaxed)) + break; + } + if (!dpio_dev) { + DPAA2_BUS_ERR("No software portal resource left"); + return NULL; + } + + DPAA2_BUS_DEBUG("New Portal %p (%d) affined thread - %u", + dpio_dev, dpio_dev->index, rte_gettid()); + +#ifdef RTE_EVENT_DPAA2 + if (dpaa2_dpio_intr_init(dpio_dev, 1, 0, false)) { + DPAA2_BUS_ERR("Interrupt registration failed for dpio"); + rte_atomic_store_explicit(&dpio_dev->ref_count, 0, + rte_memory_order_release); + return NULL; + } +#endif + + return dpio_dev; +} + +RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_free_dpio_device) +void rte_dpaa2_free_dpio_device(struct dpaa2_dpio_dev *dpio_dev) +{ + dpaa2_put_qbman_swp(dpio_dev); +} + static void dpaa2_close_dpio_device(int object_id) { diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 0838254437..59a9d11955 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -70,4 +70,12 @@ __rte_internal uint32_t dpaa2_free_eq_descriptors(void); +__rte_internal +struct dpaa2_dpio_dev * +rte_dpaa2_alloc_dpio_device(void); + +__rte_internal +void +rte_dpaa2_free_dpio_device(struct dpaa2_dpio_dev *dpio_dev); + #endif /* _DPAA2_HW_DPIO_H_ */ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 31/65] event/dpaa2: rework event port model and DPCI handling 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (29 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 30/65] bus/fslmc: add alloc/free DPIO API for non-affine portals Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 32/65] event/dpaa2: fix Tx adapter enqueue for mixed destinations Prashant Gupta ` (33 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rework the DPAA2 eventdev port model so that each event port owns a dedicated DPIO/software portal instead of relying on the per-lcore DPIO of whatever thread happens to call enqueue/dequeue. This removes the lazy link-on-first-burst logic and its error-unwind paths, and makes port behaviour independent of the calling lcore. Main changes: - Dedicated portal per event port: rte_dpaa2_alloc_dpio_device() is called at port setup and stored in struct dpaa2_port. enqueue/dequeue use portal->dpio_dev directly and reject calls on a port that was never set up or has no linked queue. An optional atomic port mode (RTE_DPAA2_EVENT_PORT_CFG_ATOMIC) takes a per-port spinlock so several lcores can share one port; otherwise the port records its affine lcore and warns on cross-lcore use. - Dynamic link and unlink: port_link now attaches DPCON static dequeue channels at link time (unlinking any previous queues first), validates queue ownership, and unwinds cleanly on failure. port_unlink removes the channels, compacts the evq_info array, and is used by port_release so a port is properly torn down. The redundant *_queue_del_all() and per-error detach unwind paths are removed. - Per-DPIO held-buffer tracking: The per-lcore DQRR bookkeeping globals (DPAA2_PER_LCORE_DQRR_*) are replaced by a dpaa2_held_bufs structure in struct dpaa2_dpio_dev, so atomic-queue DQRR state follows the portal that owns it. All dqrr callbacks now take struct dpaa2_dpio_dev * instead of struct qbman_swp *; the dpaa2_sec and net/dpaa2 callbacks are updated to match. - Event object allocation from a mempool: Each DPCI Rx queue gets an env_pool mempool of rte_event objects. enqueue takes an event from the peer queue's pool and the process callbacks return it, replacing the per-event rte_malloc/rte_free on the hot path. - Flush on stop: dpaa2_eventdev_stop() now drains each linked port and calls the registered dev_stop_flush callback for every leftover event. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpci.c | 26 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 5 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 2 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 4 +- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 32 +- drivers/event/dpaa2/dpaa2_eventdev.c | 712 ++++++++++---------- drivers/event/dpaa2/dpaa2_eventdev.h | 13 +- drivers/net/dpaa2/dpaa2_ethdev.c | 22 +- drivers/net/dpaa2/dpaa2_ethdev.h | 26 +- drivers/net/dpaa2/dpaa2_rxtx.c | 69 +- drivers/net/dpaa2/rte_pmd_dpaa2.h | 2 + 11 files changed, 464 insertions(+), 449 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c index f2bfb2a75c..f796875010 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c @@ -56,6 +56,8 @@ dpaa2_create_dpci_device(int vdev_fd __rte_unused, struct dpci_rx_queue_attr rx_attr; struct dpci_tx_queue_attr tx_attr; int ret, i, dpci_id = obj->object_id; + char pool_name[64]; + uint64_t pool_size; memset(&attr, 0, sizeof(struct dpci_attr)); memset(&peer_attr, 0, sizeof(struct dpci_peer_attr)); @@ -118,6 +120,17 @@ dpaa2_create_dpci_device(int vdev_fd __rte_unused, goto queue_err; } dpci_node->rx_queue[i].fqid = rx_attr.fqid; + snprintf(pool_name, sizeof(pool_name), "dpci%d_qid%d_env", dpci_id, i); + pool_size = RTE_ALIGN(sizeof(struct rte_event), RTE_CACHE_LINE_SIZE); + dpci_node->rx_queue[i].env_pool = rte_mempool_create(pool_name, + 1024, pool_size, 512, 0, NULL, NULL, NULL, NULL, + SOCKET_ID_ANY, 0); + if (!dpci_node->rx_queue[i].env_pool) { + DPAA2_BUS_ERR("Rx queue event pool create(%s) failed", + pool_name); + ret = -ENOMEM; + goto queue_err; + } } /* Enable the device */ @@ -177,8 +190,13 @@ dpaa2_create_dpci_device(int vdev_fd __rte_unused, rte_free(dpci_node->tx_queue); dpci_disable(&dpci_node->dpci, CMD_PRI_LOW, dpci_node->token); queue_err: - if (dpci_node->rx_queue) + if (dpci_node->rx_queue) { + for (i = 0; i < dpci_node->rx_queue_num; i++) { + if (dpci_node->rx_queue[i].env_pool) + rte_mempool_free(dpci_node->rx_queue[i].env_pool); + } rte_free(dpci_node->rx_queue); + } open_err: dpci_close(&dpci_node->dpci, CMD_PRI_LOW, dpci_node->token); @@ -223,11 +241,16 @@ static void dpaa2_close_dpci_device(int object_id) { struct dpaa2_dpci_dev *dpci_dev = NULL; + int i; dpci_dev = get_dpci_from_id((uint32_t)object_id); if (dpci_dev) { dpci_disable(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token); + for (i = 0; i < dpci_dev->rx_queue_num; i++) { + if (dpci_dev->rx_queue[i].env_pool) + rte_mempool_free(dpci_dev->rx_queue[i].env_pool); + } rte_free(dpci_dev->rx_queue); rte_free(dpci_dev->tx_queue); dpci_close(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token); @@ -285,6 +308,7 @@ rte_dpaa2_dpci_link_attach(struct dpaa2_dpci_dev *dpci_dev, return ret; } dpci_dev->rx_queue[i].cb = rx_cb; + dpci_dev->tx_queue[i].env_pool = peer_dpci->rx_queue[i].env_pool; if (txq) *txq = &dpci_dev->tx_queue[i]; diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 63e1660686..e88334088b 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -314,6 +314,7 @@ static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) * armed: intr_deinit returns early if intr is not enabled. */ dpaa2_dpio_intr_deinit(dpio_dev); + dpio_dev->cpu_affine = -1; rte_atomic_store_explicit(&dpio_dev->ref_count, 0, rte_memory_order_release); } @@ -357,6 +358,7 @@ static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(bool ethrx) return NULL; } } + dpio_dev->cpu_affine = cpu_id; ret = pthread_setspecific(dpaa2_portal_key, (void *)dpio_dev); if (ret) { @@ -424,7 +426,7 @@ static void dpaa2_portal_finish(void *arg) RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_alloc_dpio_device) struct dpaa2_dpio_dev * -rte_dpaa2_alloc_dpio_device(void) +rte_dpaa2_alloc_dpio_device(int32_t cpu_affine) { struct dpaa2_dpio_dev *dpio_dev = NULL; uint16_t expected = 0; @@ -452,6 +454,7 @@ rte_dpaa2_alloc_dpio_device(void) return NULL; } #endif + dpio_dev->cpu_affine = cpu_affine; return dpio_dev; } diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 59a9d11955..ae0f5993d6 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -72,7 +72,7 @@ dpaa2_free_eq_descriptors(void); __rte_internal struct dpaa2_dpio_dev * -rte_dpaa2_alloc_dpio_device(void); +rte_dpaa2_alloc_dpio_device(int32_t cpu_affine); __rte_internal void diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index ed82eb123a..f80abffb40 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -136,6 +136,7 @@ struct dpaa2_dpio_dev { int32_t epoll_fd; /**< File descriptor created for interrupt polling */ int32_t hw_id; /**< An unique ID of this DPIO device instance */ uint8_t intr_enabled; /**< DQRI portal interrupt already set up */ + int32_t cpu_affine; uint16_t ethrx_intr_refcnt; /**< rx queues currently armed on this portal */ struct dpaa2_portal_dqrr dpaa2_held_bufs; }; @@ -159,7 +160,7 @@ struct queue_storage_info_t { struct dpaa2_queue; -typedef void (dpaa2_queue_cb_dqrr_t)(struct qbman_swp *swp, +typedef void (dpaa2_queue_cb_dqrr_t)(struct dpaa2_dpio_dev *dpio_dev, const struct qbman_fd *fd, const struct qbman_result *dq, struct dpaa2_queue *rxq, @@ -189,6 +190,7 @@ struct __rte_cache_aligned dpaa2_queue { void *cfg; uint8_t options; struct rte_event ev; + struct rte_mempool *env_pool; dpaa2_queue_cb_dqrr_t *cb; dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free; struct dpaa2_bp_info *bp_array; diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 6e759dd821..e34ca884fe 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -4098,13 +4098,12 @@ void dpaa2_sec_stats_reset(struct rte_cryptodev *dev) } static void __rte_hot -dpaa2_sec_process_parallel_event(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +dpaa2_sec_process_parallel_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { struct dpaa2_sec_qp *qp; + struct qbman_swp *swp = dpio_dev->sw_portal; qp = container_of(rxq, struct dpaa2_sec_qp, rx_vq); ev->flow_id = rxq->ev.flow_id; @@ -4120,11 +4119,9 @@ dpaa2_sec_process_parallel_event(struct qbman_swp *swp, } static void -dpaa2_sec_process_atomic_event(struct qbman_swp *swp __rte_unused, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +dpaa2_sec_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { uint8_t dqrr_index; struct dpaa2_sec_qp *qp; @@ -4142,21 +4139,20 @@ dpaa2_sec_process_atomic_event(struct qbman_swp *swp __rte_unused, crypto_op = dpaa2_sec_fd_to_mbuf(fd, qp); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(crypto_op->sym->m_src) = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; - DPAA2_PER_LCORE_DQRR_SIZE++; - DPAA2_PER_LCORE_DQRR_HELD |= UINT64_C(1) << dqrr_index; - DPAA2_PER_LCORE_DQRR_MBUF(dqrr_index) = crypto_op->sym->m_src; + dpio_dev->dpaa2_held_bufs.dqrr_size++; + dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; + dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = crypto_op->sym->m_src; ev->event_ptr = crypto_op; } static void __rte_hot -dpaa2_sec_process_ordered_event(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +dpaa2_sec_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { struct rte_crypto_op *crypto_op; struct dpaa2_sec_qp *qp; + struct qbman_swp *swp = dpio_dev->sw_portal; qp = container_of(rxq, struct dpaa2_sec_qp, rx_vq); ev->flow_id = rxq->ev.flow_id; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 28ed07bd97..03016d2a12 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -51,66 +51,66 @@ #define DPAA2_EV_TX_RETRY_COUNT 10000 +static __rte_always_inline struct dpaa2_dpio_dev * +dpaa2_event_portal_io_prepare(struct dpaa2_port *dpaa2_portal) +{ + struct dpaa2_dpio_dev *dpio_dev; + + if (unlikely(!dpaa2_portal->dpio_dev)) { + DPAA2_EVENTDEV_ERR("Event port%d not setup", dpaa2_portal->port_id); + return NULL; + } + + if (unlikely(!dpaa2_portal->num_linked_evq)) { + DPAA2_EVENTDEV_WARN("Event port%d no queue linked", + dpaa2_portal->port_id); + rte_delay_us(10000); + return NULL; + } + + dpio_dev = dpaa2_portal->dpio_dev; + + if (unlikely(!dpaa2_portal->port_atomic && + !rte_atomic_load_explicit(&dpaa2_portal->flushing, + rte_memory_order_relaxed)) && + dpio_dev->cpu_affine != (int32_t)rte_lcore_id()) { + DPAA2_EVENTDEV_DEBUG("Event port%d affine CPU from %d->%d", + dpaa2_portal->port_id, dpio_dev->cpu_affine, rte_lcore_id()); + dpio_dev->cpu_affine = rte_lcore_id(); + } + + return dpio_dev; +} + static uint16_t dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], - uint16_t nb_events) + uint16_t nb_events) { struct dpaa2_port *dpaa2_portal = port; struct dpaa2_dpio_dev *dpio_dev; struct rte_eventdev *eventdev = dpaa2_portal->eventdev; struct dpaa2_eventdev *priv = eventdev->data->dev_private; struct dpaa2_eventq *evq_info; - uint32_t queue_id, retry_count; + uint32_t queue_id, retry_count, loop, frames_to_send, i; struct qbman_swp *swp; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - uint32_t loop, frames_to_send; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; uint16_t num_tx = 0; - int i, n, ret; - uint8_t channel_index; + int ret; + uint8_t dqrr_index; const struct rte_event *event; - struct dpaa2_queue *dpci_txq; - - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - /* Affine current thread context to a qman portal */ - ret = dpaa2_affine_qbman_swp(); - if (ret < 0) { - DPAA2_EVENTDEV_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); - return 0; - } - } - /* todo - dpaa2_portal shall have dpio_dev - no per thread variable */ - dpio_dev = DPAA2_PER_LCORE_DPIO; - swp = DPAA2_PER_LCORE_PORTAL; + struct dpaa2_queue *dpci_txq[MAX_TX_RING_SLOTS]; + struct rte_event *ev_tx[MAX_TX_RING_SLOTS]; - if (likely(dpaa2_portal->is_port_linked)) - goto skip_linking; + if (unlikely(dpaa2_portal->port_atomic)) + rte_spinlock_lock(&dpaa2_portal->port_lock); - /* Create mapping between portal and channel to receive packets */ - for (i = 0; i < DPAA2_EVENT_MAX_QUEUES; i++) { - evq_info = &dpaa2_portal->evq_info[i]; - if (!evq_info->event_port) - continue; + dpio_dev = dpaa2_event_portal_io_prepare(dpaa2_portal); + if (!dpio_dev) + goto quit; - ret = dpio_add_static_dequeue_channel(dpio_dev->dpio, - CMD_PRI_LOW, - dpio_dev->token, - evq_info->dpcon->dpcon_id, - &channel_index); - if (ret < 0) { - DPAA2_EVENTDEV_ERR( - "Static dequeue config failed: err(%d)", ret); - goto err; - } + swp = dpio_dev->sw_portal; - qbman_swp_push_set(swp, channel_index, 1); - evq_info->dpcon->channel_index = channel_index; - } - dpaa2_portal->is_port_linked = true; - -skip_linking: while (nb_events) { frames_to_send = (nb_events > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_events; @@ -133,23 +133,27 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], ret = -ENOTSUP; goto send_partial; } - dpci_txq = evq_info->dpci_txqs[event->sched_type]; + dpci_txq[loop] = evq_info->dpci_txqs[event->sched_type]; + + ret = rte_mempool_get(dpci_txq[loop]->env_pool, (void **)&ev_tx[loop]); + if (ret) { + DPAA2_EVENTDEV_ERR("Allocate event object failed from %s", + dpci_txq[loop]->env_pool->name); + goto send_partial; + } /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); - qbman_eq_desc_set_fq(&eqdesc[loop], dpci_txq->fqid); + qbman_eq_desc_set_fq(&eqdesc[loop], dpci_txq[loop]->fqid); qbman_eq_desc_set_no_orp(&eqdesc[loop], 0); qbman_eq_desc_set_response(&eqdesc[loop], 0, 0); - if (event->sched_type == RTE_SCHED_TYPE_ATOMIC - && *dpaa2_seqn(event->mbuf)) { - uint8_t dqrr_index = - *dpaa2_seqn(event->mbuf) - 1; - - qbman_eq_desc_set_dca(&eqdesc[loop], 1, - dqrr_index, 0); - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(1 << dqrr_index); + if (event->sched_type == RTE_SCHED_TYPE_ATOMIC && + *dpaa2_seqn(event->mbuf)) { + dqrr_index = *dpaa2_seqn(event->mbuf) - 1; + qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); + dpio_dev->dpaa2_held_bufs.dqrr_size--; + dpio_dev->dpaa2_held_bufs.dqrr_held &= ~(1 << dqrr_index); } memset(&fd_arr[loop], 0, sizeof(struct qbman_fd)); @@ -158,23 +162,13 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], * todo - need to align with hw context data * to avoid copy */ - struct rte_event *ev_temp = rte_malloc(NULL, - sizeof(struct rte_event), 0); - - if (!ev_temp) { - if (!loop) - return num_tx; - frames_to_send = loop; - DPAA2_EVENTDEV_ERR( - "Unable to allocate event object"); - goto send_partial; - } - rte_memcpy(ev_temp, event, sizeof(struct rte_event)); - DPAA2_SET_FD_ADDR((&fd_arr[loop]), (size_t)ev_temp); - DPAA2_SET_FD_LEN((&fd_arr[loop]), - sizeof(struct rte_event)); + + rte_memcpy(ev_tx[loop], event, sizeof(struct rte_event)); + DPAA2_SET_FD_ADDR((&fd_arr[loop]), (size_t)ev_tx[loop]); + DPAA2_SET_FD_LEN((&fd_arr[loop]), sizeof(struct rte_event)); } send_partial: + frames_to_send = loop; loop = 0; retry_count = 0; while (loop < frames_to_send) { @@ -186,7 +180,9 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], if (retry_count > DPAA2_EV_TX_RETRY_COUNT) { num_tx += loop; nb_events -= loop; - return num_tx; + for (i = loop; i < frames_to_send; i++) + rte_mempool_put(dpci_txq[i]->env_pool, ev_tx[i]); + goto quit; } } else { loop += ret; @@ -197,19 +193,10 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], nb_events -= loop; } +quit: + if (dpaa2_portal->port_atomic) + rte_spinlock_unlock(&dpaa2_portal->port_lock); return num_tx; -err: - for (n = 0; n < i; n++) { - evq_info = &dpaa2_portal->evq_info[n]; - if (!evq_info->event_port) - continue; - qbman_swp_push_set(swp, evq_info->dpcon->channel_index, 0); - dpio_remove_static_dequeue_channel(dpio_dev->dpio, 0, - dpio_dev->token, - evq_info->dpcon->dpcon_id); - } - return 0; - } static void dpaa2_eventdev_dequeue_wait(uint64_t timeout_ticks) @@ -223,109 +210,72 @@ static void dpaa2_eventdev_dequeue_wait(uint64_t timeout_ticks) &epoll_ev, 1, timeout_ticks); } -static void dpaa2_eventdev_process_parallel(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +static void dpaa2_eventdev_process_parallel(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { - struct rte_event *ev_temp = - (struct rte_event *)(size_t)DPAA2_GET_FD_ADDR(fd); + struct rte_event *rx_ev = (void *)DPAA2_GET_FD_ADDR(fd); + struct qbman_swp *swp = dpio_dev->sw_portal; - RTE_SET_USED(rxq); - - *ev = *ev_temp; - rte_free(ev_temp); + rte_memcpy(ev, rx_ev, sizeof(struct rte_event)); + rte_mempool_put(rxq->env_pool, rx_ev); qbman_swp_dqrr_consume(swp, dq); } -static void dpaa2_eventdev_process_atomic(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +static void dpaa2_eventdev_process_atomic(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { - struct rte_event *ev_temp = - (struct rte_event *)(size_t)DPAA2_GET_FD_ADDR(fd); + struct rte_event *rx_ev = (void *)DPAA2_GET_FD_ADDR(fd); uint8_t dqrr_index = qbman_get_dqrr_idx(dq); - RTE_SET_USED(swp); - RTE_SET_USED(rxq); - - *ev = *ev_temp; - rte_free(ev_temp); + rte_memcpy(ev, rx_ev, sizeof(struct rte_event)); + rte_mempool_put(rxq->env_pool, rx_ev); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; - DPAA2_PER_LCORE_DQRR_SIZE++; - DPAA2_PER_LCORE_DQRR_HELD |= 1 << dqrr_index; - DPAA2_PER_LCORE_DQRR_MBUF(dqrr_index) = ev->mbuf; + dpio_dev->dpaa2_held_bufs.dqrr_size++; + dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; + dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = ev->mbuf; } static uint16_t dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], - uint16_t nb_events, uint64_t timeout_ticks) + uint16_t nb_events, uint64_t timeout_ticks) { const struct qbman_result *dq; - struct dpaa2_dpio_dev *dpio_dev = NULL; + struct dpaa2_dpio_dev *dpio_dev; struct dpaa2_port *dpaa2_portal = port; - struct dpaa2_eventq *evq_info; struct qbman_swp *swp; const struct qbman_fd *fd; struct dpaa2_queue *rxq; - int num_pkts = 0, ret, i = 0, n; - uint8_t channel_index; + uint16_t num_pkts = 0, i = 0; - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - /* Affine current thread context to a qman portal */ - ret = dpaa2_affine_qbman_swp(); - if (ret < 0) { - DPAA2_EVENTDEV_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); - return 0; - } - } + if (unlikely(dpaa2_portal->port_atomic)) + rte_spinlock_lock(&dpaa2_portal->port_lock); - dpio_dev = DPAA2_PER_LCORE_DPIO; - swp = DPAA2_PER_LCORE_PORTAL; + dpio_dev = dpaa2_event_portal_io_prepare(dpaa2_portal); + if (!dpio_dev) + goto quit; - if (likely(dpaa2_portal->is_port_linked)) - goto skip_linking; + swp = dpio_dev->sw_portal; - /* Create mapping between portal and channel to receive packets */ - for (i = 0; i < DPAA2_EVENT_MAX_QUEUES; i++) { - evq_info = &dpaa2_portal->evq_info[i]; - if (!evq_info->event_port) - continue; + /* Check if there are atomic contexts to be released */ - ret = dpio_add_static_dequeue_channel(dpio_dev->dpio, - CMD_PRI_LOW, - dpio_dev->token, - evq_info->dpcon->dpcon_id, - &channel_index); - if (ret < 0) { - DPAA2_EVENTDEV_ERR( - "Static dequeue config failed: err(%d)", ret); - goto err; + while (dpio_dev->dpaa2_held_bufs.dqrr_size) { + if (i >= DPAA2_PORTAL_DEQUEUE_DEPTH) { + DPAA2_EVENTDEV_WARN("Too many hold dqrrs(%d)", + dpio_dev->dpaa2_held_bufs.dqrr_size); + break; } - - qbman_swp_push_set(swp, channel_index, 1); - evq_info->dpcon->channel_index = channel_index; - } - dpaa2_portal->is_port_linked = true; - -skip_linking: - /* Check if there are atomic contexts to be released */ - while (DPAA2_PER_LCORE_DQRR_SIZE) { - if (DPAA2_PER_LCORE_DQRR_HELD & (1 << i)) { + if (dpio_dev->dpaa2_held_bufs.dqrr_held & (UINT64_C(1) << i)) { qbman_swp_dqrr_idx_consume(swp, i); - DPAA2_PER_LCORE_DQRR_SIZE--; - *dpaa2_seqn(DPAA2_PER_LCORE_DQRR_MBUF(i)) = + dpio_dev->dpaa2_held_bufs.dqrr_size--; + *dpaa2_seqn(dpio_dev->dpaa2_held_bufs.mbuf[i]) = DPAA2_INVALID_MBUF_SEQN; } i++; } - DPAA2_PER_LCORE_DQRR_HELD = 0; + dpio_dev->dpaa2_held_bufs.dqrr_held = 0; do { dq = qbman_swp_dqrr_next(swp); @@ -339,48 +289,34 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], timeout_ticks = 0; continue; } - return num_pkts; + goto quit; } qbman_swp_prefetch_dqrr_next(swp); fd = qbman_result_DQ_fd(dq); - rxq = (struct dpaa2_queue *)(size_t)qbman_result_DQ_fqd_ctx(dq); - if (rxq) { - rxq->cb(swp, fd, dq, rxq, &ev[num_pkts]); - } else { + rxq = (void *)qbman_result_DQ_fqd_ctx(dq); + if (rxq && rxq->cb) + rxq->cb(dpio_dev, fd, dq, rxq, &ev[num_pkts]); + else qbman_swp_dqrr_consume(swp, dq); - DPAA2_EVENTDEV_ERR("Null Return VQ received"); - return 0; - } num_pkts++; } while (num_pkts < nb_events); +quit: + if (dpaa2_portal->port_atomic) + rte_spinlock_unlock(&dpaa2_portal->port_lock); return num_pkts; -err: - for (n = 0; n < i; n++) { - evq_info = &dpaa2_portal->evq_info[n]; - if (!evq_info->event_port) - continue; - - qbman_swp_push_set(swp, evq_info->dpcon->channel_index, 0); - dpio_remove_static_dequeue_channel(dpio_dev->dpio, 0, - dpio_dev->token, - evq_info->dpcon->dpcon_id); - } - return 0; } static void dpaa2_eventdev_info_get(struct rte_eventdev *dev, - struct rte_event_dev_info *dev_info) + struct rte_event_dev_info *dev_info) { struct dpaa2_eventdev *priv = dev->data->dev_private; EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); - memset(dev_info, 0, sizeof(struct rte_event_dev_info)); dev_info->min_dequeue_timeout_ns = DPAA2_EVENT_MIN_DEQUEUE_TIMEOUT; @@ -396,6 +332,8 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, dev_info->max_event_priority_levels = DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS; dev_info->max_event_ports = rte_fslmc_get_device_count(DPAA2_IO); + if (dev_info->max_event_ports > dev_info->max_event_queues) + dev_info->max_event_ports = dev_info->max_event_queues; /* we only support dpio up to number of cores */ if (dev_info->max_event_ports > rte_lcore_count()) dev_info->max_event_ports = rte_lcore_count(); @@ -464,9 +402,42 @@ dpaa2_eventdev_start(struct rte_eventdev *dev) static void dpaa2_eventdev_stop(struct rte_eventdev *dev) { + uint16_t num, i, max; + struct rte_event ev; + struct dpaa2_port *dpaa2_portal; + EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); + for (i = 0; i < dev->data->nb_ports; i++) { + dpaa2_portal = dev->data->ports[i]; + if (!dpaa2_portal || !dpaa2_portal->num_linked_evq) + continue; + /* Workers must be quiesced before rte_event_dev_stop() is called. + * Concurrent portal access from a worker lcore during drain is undefined. + * Mark the port as draining so the dequeue path skips the + * cross-lcore warning. Do not touch cpu_affine here: it is + * read on the data path and mutating it would be a data race. + */ + rte_atomic_store_explicit(&dpaa2_portal->flushing, 1, + rte_memory_order_relaxed); + max = 0; +dq_again: + rte_delay_us(100); + num = dpaa2_eventdev_dequeue_burst(dpaa2_portal, &ev, 1, 1); + max++; + if (num && dev->dev_ops->dev_stop_flush) { + dev->dev_ops->dev_stop_flush(dev->data->dev_id, + ev, dev->data->dev_stop_flush_arg); + } + if (!num || max > 10000) { + rte_atomic_store_explicit(&dpaa2_portal->flushing, 0, + rte_memory_order_relaxed); + if (max > 10000 && num) + DPAA2_EVENTDEV_WARN("Quit with pending buffers"); + continue; + } + goto dq_again; + } } static int @@ -543,116 +514,218 @@ dpaa2_eventdev_port_def_conf(struct rte_eventdev *dev, uint8_t port_id, } static int -dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, - const struct rte_event_port_conf *port_conf) +dpaa2_eventdev_port_unlink(struct rte_eventdev *dev, void *port, + uint8_t queues[], uint16_t nb_unlinks) { - char event_port_name[32]; - struct dpaa2_port *portal; + struct dpaa2_port *dpaa2_portal = port; + int i, j, ret, num = 0, idx = 0; + struct dpaa2_dpio_dev *dpio_dev = NULL; + struct dpaa2_eventq *evq_info; + struct qbman_swp *swp; + uint8_t total_queues[DPAA2_EVENT_MAX_QUEUES]; + struct dpaa2_eventq *evq_infos[DPAA2_EVENT_MAX_QUEUES]; EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(port_conf); - - sprintf(event_port_name, "event-port-%d", port_id); - portal = rte_zmalloc(event_port_name, sizeof(struct dpaa2_port), 0); - if (!portal) { - DPAA2_EVENTDEV_ERR("Memory allocation failure"); - return -ENOMEM; + RTE_SET_USED(dev); + if (!queues) { + queues = total_queues; + nb_unlinks = dpaa2_portal->num_linked_evq; + for (i = 0; i < nb_unlinks; i++) + queues[i] = dpaa2_portal->evq_info[i]->event_queue_id; } - portal->eventdev = dev; - portal->port_id = port_id; - dev->data->ports[port_id] = portal; - return 0; -} - -static void -dpaa2_eventdev_port_release(void *port) -{ - struct dpaa2_port *portal = port; - - EVENTDEV_INIT_FUNC_TRACE(); + for (i = 0; i < nb_unlinks; i++) { + for (j = 0; j < dpaa2_portal->num_linked_evq; j++) { + evq_info = dpaa2_portal->evq_info[j]; + if (evq_info && evq_info->event_queue_id == queues[i]) { + dpio_dev = dpaa2_portal->dpio_dev; + swp = dpio_dev->sw_portal; + qbman_swp_push_set(swp, evq_info->dpcon->channel_index, 0); + ret = dpio_remove_static_dequeue_channel(dpio_dev->dpio, + 0, dpio_dev->token, evq_info->dpcon->dpcon_id); + if (ret) + DPAA2_EVENTDEV_WARN("Failed(%d) to remove channel", ret); + evq_info->event_port = NULL; + dpaa2_portal->evq_info[j] = NULL; + num++; + break; + } + } + if (j == dpaa2_portal->num_linked_evq) { + DPAA2_EVENTDEV_WARN("%s: Event port%d doesn't handle queue[%d]:%d", + __func__, dpaa2_portal->port_id, i, queues[i]); + } + } - if (portal == NULL) - return; + for (i = 0; i < dpaa2_portal->num_linked_evq; i++) { + if (dpaa2_portal->evq_info[i]) { + evq_infos[idx] = dpaa2_portal->evq_info[i]; + idx++; + dpaa2_portal->evq_info[i] = NULL; + } + } + for (i = 0; i < idx; i++) + dpaa2_portal->evq_info[i] = evq_infos[i]; - /* TODO: Cleanup is required when ports are in linked state. */ - if (portal->is_port_linked) - DPAA2_EVENTDEV_WARN("Event port must be unlinked before release"); + dpaa2_portal->num_linked_evq -= num; - rte_free(portal); + return num; } static int dpaa2_eventdev_port_link(struct rte_eventdev *dev, void *port, - const uint8_t queues[], const uint8_t priorities[], - uint16_t nb_links) + const uint8_t queues[], const uint8_t priorities[], + uint16_t nb_links) { struct dpaa2_eventdev *priv = dev->data->dev_private; - struct dpaa2_port *dpaa2_portal = port; + struct dpaa2_port *dpaa2_portal = port, *ev_port; + struct dpaa2_dpio_dev *dpio_dev = dpaa2_portal->dpio_dev; struct dpaa2_eventq *evq_info; + int ret = 0; uint16_t i; + uint8_t channel_index; EVENTDEV_INIT_FUNC_TRACE(); RTE_SET_USED(priorities); + if (dpaa2_portal->num_linked_evq > 0) { + ret = rte_event_port_unlink(dev->data->dev_id, + dpaa2_portal->port_id, NULL, 0); + if (ret) + return ret; + } + + for (i = 0; i < nb_links; i++) { + evq_info = &priv->evq_info[queues[i]]; + if (!evq_info->valid) { + DPAA2_EVENTDEV_WARN("%s: Event port%d.queue%d is not valid!", + __func__, dpaa2_portal->port_id, queues[i]); + return -EINVAL; + } + if (evq_info->event_port) { + ev_port = evq_info->event_port; + DPAA2_EVENTDEV_WARN("%s: queue%d is occupied by event port%d", + __func__, queues[i], ev_port->port_id); + return -ENODEV; + } + } + for (i = 0; i < nb_links; i++) { evq_info = &priv->evq_info[queues[i]]; - dpaa2_portal->evq_info[queues[i]] = *evq_info; - dpaa2_portal->evq_info[queues[i]].event_port = port; + ret = dpio_add_static_dequeue_channel(dpio_dev->dpio, + CMD_PRI_LOW, dpio_dev->token, + evq_info->dpcon->dpcon_id, &channel_index); + if (ret) { + DPAA2_EVENTDEV_ERR("Event port%d.queue%d static dequeue config failed(%d)", + dpaa2_portal->port_id, queues[i], ret); + goto err; + } + + qbman_swp_push_set(dpio_dev->sw_portal, channel_index, 1); + evq_info->dpcon->channel_index = channel_index; + + dpaa2_portal->evq_info[dpaa2_portal->num_linked_evq] = evq_info; + evq_info->event_port = dpaa2_portal; dpaa2_portal->num_linked_evq++; } - return (int)nb_links; +err: + if (!ret) + return nb_links; + + nb_links = i; + for (i = 0; i < nb_links; i++) { + evq_info = &priv->evq_info[queues[i]]; + evq_info->event_port = NULL; + qbman_swp_push_set(dpio_dev->sw_portal, evq_info->dpcon->channel_index, 0); + if (dpio_remove_static_dequeue_channel(dpio_dev->dpio, + 0, dpio_dev->token, evq_info->dpcon->dpcon_id)) { + DPAA2_EVENTDEV_ERR("Event port%d.queue%d remove failed!", + dpaa2_portal->port_id, queues[i]); + } + dpaa2_portal->num_linked_evq--; + } + return ret; } -static int -dpaa2_eventdev_port_unlink(struct rte_eventdev *dev, void *port, - uint8_t queues[], uint16_t nb_unlinks) +static void +dpaa2_eventdev_port_release(void *port) { - struct dpaa2_port *dpaa2_portal = port; - int i; - struct dpaa2_dpio_dev *dpio_dev = NULL; - struct dpaa2_eventq *evq_info; - struct qbman_swp *swp; + struct dpaa2_port *portal = port; + uint8_t port_id; + struct rte_eventdev *eventdev; + int ret; EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); - RTE_SET_USED(queues); + if (!portal) + return; - for (i = 0; i < nb_unlinks; i++) { - evq_info = &dpaa2_portal->evq_info[queues[i]]; - - if (DPAA2_PER_LCORE_DPIO && evq_info->dpcon) { - /* todo dpaa2_portal shall have dpio_dev-no per lcore*/ - dpio_dev = DPAA2_PER_LCORE_DPIO; - swp = DPAA2_PER_LCORE_PORTAL; - - qbman_swp_push_set(swp, - evq_info->dpcon->channel_index, 0); - dpio_remove_static_dequeue_channel(dpio_dev->dpio, 0, - dpio_dev->token, - evq_info->dpcon->dpcon_id); + port_id = portal->port_id; + eventdev = portal->eventdev; + + /* TODO: Cleanup is required when ports are in linked state. */ + if (portal->num_linked_evq && eventdev) { + ret = rte_event_port_unlink(eventdev->data->dev_id, port_id, NULL, 0); + if (ret < 0) { + DPAA2_EVENTDEV_ERR("Event port.%d unlink all failed(%d)", + portal->port_id, ret); } - memset(evq_info, 0, sizeof(struct dpaa2_eventq)); - if (dpaa2_portal->num_linked_evq) - dpaa2_portal->num_linked_evq--; } - if (!dpaa2_portal->num_linked_evq) - dpaa2_portal->is_port_linked = false; + if (portal->dpio_dev) + rte_dpaa2_free_dpio_device(portal->dpio_dev); - return (int)nb_unlinks; + rte_free(portal); + if (eventdev) + eventdev->data->ports[port_id] = NULL; } +static int +dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, + const struct rte_event_port_conf *port_conf) +{ + char event_port_name[32]; + struct dpaa2_port *portal; + + EVENTDEV_INIT_FUNC_TRACE(); + + if (dev->data->ports[port_id]) { + DPAA2_EVENTDEV_WARN("Event port%d exists!", port_id); + dpaa2_eventdev_port_release(dev->data->ports[port_id]); + } + + sprintf(event_port_name, "event-port-%d", port_id); + portal = rte_zmalloc(event_port_name, sizeof(struct dpaa2_port), 0); + if (!portal) { + DPAA2_EVENTDEV_ERR("Memory allocation failure"); + return -ENOMEM; + } + + portal->dpio_dev = rte_dpaa2_alloc_dpio_device(-1); + if (!portal->dpio_dev) { + rte_free(portal); + return -ENODEV; + } + if (port_conf && + (port_conf->event_port_cfg & RTE_DPAA2_EVENT_PORT_CFG_ATOMIC)) { + portal->port_atomic = true; + rte_spinlock_init(&portal->port_lock); + } + portal->eventdev = dev; + + portal->port_id = port_id; + dev->data->ports[port_id] = portal; + return 0; +} static int dpaa2_eventdev_timeout_ticks(struct rte_eventdev *dev, uint64_t ns, uint64_t *timeout_ticks) { - uint32_t scale = 1000*1000; + uint32_t scale = 1000 * 1000; EVENTDEV_INIT_FUNC_TRACE(); @@ -673,16 +746,13 @@ dpaa2_eventdev_dump(struct rte_eventdev *dev, FILE *f) static int dpaa2_eventdev_eth_caps_get(const struct rte_eventdev *dev, - const struct rte_eth_dev *eth_dev, - uint32_t *caps) + const struct rte_eth_dev *eth_dev, uint32_t *caps) { - const char *ethdev_driver = eth_dev->device->driver->name; - EVENTDEV_INIT_FUNC_TRACE(); RTE_SET_USED(dev); - if (!strcmp(ethdev_driver, "net_dpaa2")) + if (rte_pmd_dpaa2_dev_is_dpaa2(eth_dev->data->port_id)) *caps = RTE_EVENT_ETH_RX_ADAPTER_DPAA2_CAP; else *caps = RTE_EVENT_ETH_RX_ADAPTER_SW_CAP; @@ -703,11 +773,9 @@ dpaa2_eventdev_eth_queue_add_all(const struct rte_eventdev *dev, EVENTDEV_INIT_FUNC_TRACE(); for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { - ret = dpaa2_eth_eventq_attach(eth_dev, i, - dpcon, queue_conf); + ret = dpaa2_eth_eventq_attach(eth_dev, i, dpcon, queue_conf); if (ret) { - DPAA2_EVENTDEV_ERR( - "Event queue attach failed: err(%d)", ret); + DPAA2_EVENTDEV_ERR("Event queue attach failed: err(%d)", ret); goto fail; } } @@ -732,40 +800,14 @@ dpaa2_eventdev_eth_queue_add(const struct rte_eventdev *dev, EVENTDEV_INIT_FUNC_TRACE(); - if (rx_queue_id == -1) - return dpaa2_eventdev_eth_queue_add_all(dev, - eth_dev, queue_conf); - - ret = dpaa2_eth_eventq_attach(eth_dev, rx_queue_id, - dpcon, queue_conf); - if (ret) { - DPAA2_EVENTDEV_ERR( - "Event queue attach failed: err(%d)", ret); - return ret; - } - return 0; -} - -static int -dpaa2_eventdev_eth_queue_del_all(const struct rte_eventdev *dev, - const struct rte_eth_dev *eth_dev) -{ - int i, ret; - - EVENTDEV_INIT_FUNC_TRACE(); - - RTE_SET_USED(dev); + if (rx_queue_id < 0) + return dpaa2_eventdev_eth_queue_add_all(dev, eth_dev, queue_conf); - for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { - ret = dpaa2_eth_eventq_detach(eth_dev, i); - if (ret) { - DPAA2_EVENTDEV_ERR( - "Event queue detach failed: err(%d)", ret); - return ret; - } - } + ret = dpaa2_eth_eventq_attach(eth_dev, rx_queue_id, dpcon, queue_conf); + if (ret) + DPAA2_EVENTDEV_ERR("Event queue attach failed: err(%d)", ret); - return 0; + return ret; } static int @@ -773,19 +815,11 @@ dpaa2_eventdev_eth_queue_del(const struct rte_eventdev *dev, const struct rte_eth_dev *eth_dev, int32_t rx_queue_id) { - int ret; - EVENTDEV_INIT_FUNC_TRACE(); - if (rx_queue_id == -1) - return dpaa2_eventdev_eth_queue_del_all(dev, eth_dev); - - ret = dpaa2_eth_eventq_detach(eth_dev, rx_queue_id); - if (ret) { - DPAA2_EVENTDEV_ERR( - "Event queue detach failed: err(%d)", ret); - return ret; - } + RTE_SET_USED(dev); + RTE_SET_USED(eth_dev); + RTE_SET_USED(rx_queue_id); return 0; } @@ -848,8 +882,7 @@ dpaa2_eventdev_crypto_queue_add_all(const struct rte_eventdev *dev, for (i = 0; i < cryptodev->data->nb_queue_pairs; i++) { ret = dpaa2_sec_eventq_attach(cryptodev, i, dpcon, ev); if (ret) { - DPAA2_EVENTDEV_ERR("dpaa2_sec_eventq_attach failed: ret %d", - ret); + DPAA2_EVENTDEV_ERR("Event queue attach failed: err(%d)", ret); goto fail; } } @@ -863,9 +896,8 @@ dpaa2_eventdev_crypto_queue_add_all(const struct rte_eventdev *dev, static int dpaa2_eventdev_crypto_queue_add(const struct rte_eventdev *dev, - const struct rte_cryptodev *cryptodev, - int32_t rx_queue_id, - const struct rte_event_crypto_adapter_queue_conf *conf) + const struct rte_cryptodev *cryptodev, int32_t qp, + const struct rte_event_crypto_adapter_queue_conf *conf) { struct dpaa2_eventdev *priv = dev->data->dev_private; uint8_t ev_qid = conf->ev.queue_id; @@ -874,63 +906,34 @@ dpaa2_eventdev_crypto_queue_add(const struct rte_eventdev *dev, EVENTDEV_INIT_FUNC_TRACE(); - if (rx_queue_id == -1) - return dpaa2_eventdev_crypto_queue_add_all(dev, - cryptodev, &conf->ev); + if (qp < 0) + return dpaa2_eventdev_crypto_queue_add_all(dev, cryptodev, &conf->ev); - ret = dpaa2_sec_eventq_attach(cryptodev, rx_queue_id, - dpcon, &conf->ev); - if (ret) { - DPAA2_EVENTDEV_ERR( - "dpaa2_sec_eventq_attach failed: ret: %d", ret); - return ret; - } - return 0; + ret = dpaa2_sec_eventq_attach(cryptodev, qp, dpcon, &conf->ev); + if (ret) + DPAA2_EVENTDEV_ERR("Failed(%d) to attach SEC qp.%d", ret, qp); + + return ret; } static int -dpaa2_eventdev_crypto_queue_del_all(const struct rte_eventdev *dev, - const struct rte_cryptodev *cdev) +dpaa2_eventdev_crypto_queue_del(const struct rte_eventdev *dev, + const struct rte_cryptodev *cryptodev, int32_t qp) { int i, ret; - EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); - - for (i = 0; i < cdev->data->nb_queue_pairs; i++) { - ret = dpaa2_sec_eventq_detach(cdev, i); - if (ret) { - DPAA2_EVENTDEV_ERR( - "dpaa2_sec_eventq_detach failed:ret %d", ret); - return ret; + if (qp < 0) { + for (i = 0; i < cryptodev->data->nb_queue_pairs; i++) { + ret = dpaa2_sec_eventq_detach(cryptodev, i); + if (ret) + DPAA2_EVENTDEV_ERR("Failed(%d) to detach qp.%d", ret, i); } + return 0; } - - return 0; + return dpaa2_sec_eventq_detach(cryptodev, qp); } -static int -dpaa2_eventdev_crypto_queue_del(const struct rte_eventdev *dev, - const struct rte_cryptodev *cryptodev, - int32_t rx_queue_id) -{ - int ret; - - EVENTDEV_INIT_FUNC_TRACE(); - - if (rx_queue_id == -1) - return dpaa2_eventdev_crypto_queue_del_all(dev, cryptodev); - - ret = dpaa2_sec_eventq_detach(cryptodev, rx_queue_id); - if (ret) { - DPAA2_EVENTDEV_ERR( - "dpaa2_sec_eventq_detach failed: ret: %d", ret); - return ret; - } - - return 0; -} static int dpaa2_eventdev_crypto_start(const struct rte_eventdev *dev, @@ -981,8 +984,7 @@ dpaa2_eventdev_tx_adapter_caps(const struct rte_eventdev *dev, static uint16_t dpaa2_eventdev_txa_enqueue_same_dest(void *port, - struct rte_event ev[], - uint16_t nb_events) + struct rte_event ev[], uint16_t nb_events) { struct rte_mbuf *m[MAX_TX_RING_SLOTS], *m0; uint16_t sent = 0, burst, i, port_id; @@ -1013,8 +1015,7 @@ dpaa2_eventdev_txa_enqueue_same_dest(void *port, static uint16_t dpaa2_eventdev_txa_enqueue(void *port, - struct rte_event ev[], - uint16_t nb_events) + struct rte_event ev[], uint16_t nb_events) { void *txq[MAX_TX_RING_SLOTS]; struct rte_mbuf *m[MAX_TX_RING_SLOTS]; @@ -1088,13 +1089,13 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) goto fail; } - eventdev->dev_ops = &dpaa2_eventdev_ops; + eventdev->dev_ops = &dpaa2_eventdev_ops; eventdev->enqueue_burst = dpaa2_eventdev_enqueue_burst; eventdev->enqueue_new_burst = dpaa2_eventdev_enqueue_burst; eventdev->enqueue_forward_burst = dpaa2_eventdev_enqueue_burst; eventdev->dequeue_burst = dpaa2_eventdev_dequeue_burst; - eventdev->txa_enqueue = dpaa2_eventdev_txa_enqueue; - eventdev->txa_enqueue_same_dest = dpaa2_eventdev_txa_enqueue_same_dest; + eventdev->txa_enqueue = dpaa2_eventdev_txa_enqueue; + eventdev->txa_enqueue_same_dest = dpaa2_eventdev_txa_enqueue_same_dest; /* For secondary processes, the primary has done all the work */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) @@ -1145,6 +1146,8 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) evq_info->event_port = NULL; priv->max_event_queues++; + if (priv->max_event_queues >= DPAA2_EVENT_MAX_QUEUES) + break; } while (dpcon_dev && dpci_dev); DPAA2_EVENTDEV_INFO("%s eventdev created", name); @@ -1164,9 +1167,9 @@ dpaa2_eventdev_destroy(const char *name) int i; eventdev = rte_event_pmd_get_named_dev(name); - if (eventdev == NULL) { + if (!eventdev) { DPAA2_EVENTDEV_ERR("eventdev with name %s not allocated", name); - return -1; + return -ENODEV; } /* For secondary processes, the primary has done all the work */ @@ -1188,7 +1191,6 @@ dpaa2_eventdev_destroy(const char *name) return 0; } - static int dpaa2_eventdev_probe(struct rte_vdev_device *vdev) { diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index 9f0abae9d4..b6f23ec2e2 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -67,10 +67,19 @@ struct dpaa2_eventq { struct dpaa2_port { struct rte_eventdev *eventdev; - struct dpaa2_eventq evq_info[DPAA2_EVENT_MAX_QUEUES]; + struct dpaa2_dpio_dev *dpio_dev; + int port_atomic; + rte_spinlock_t port_lock; + /* + * Set by the control thread while draining this port in the stop + * path. Read on the data path to suppress the cross-lcore warning + * without mutating cpu_affine (which would race with the data path). + */ + RTE_ATOMIC(uint32_t) flushing; + + struct dpaa2_eventq *evq_info[DPAA2_EVENT_MAX_QUEUES]; uint8_t port_id; uint8_t num_linked_evq; - uint8_t is_port_linked; uint64_t timeout_us; }; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 9002556b91..552ac4c94d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3315,11 +3315,10 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, const struct rte_event_eth_rx_adapter_queue_conf *queue_conf) { struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; - struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; + struct fsl_mc_io *dpni = dev->process_private; struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; - uint8_t flow_id = dpaa2_ethq->flow_id; + uint8_t flow_id = dpaa2_ethq->flow_id, options, priority; struct dpni_queue *cfg; - uint8_t options, priority; int ret; cfg = dpaa2_ethq->cfg; @@ -3352,7 +3351,7 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, } if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED && - !eth_priv->en_ordered) { + !eth_priv->en_ordered) { struct opr_cfg ocfg; /* Restoration window size = 256 frames */ @@ -3376,10 +3375,10 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, } ret = dpni_set_opr(dpni, CMD_PRI_LOW, eth_priv->token, - dpaa2_ethq->tc_index, flow_id, - OPR_OPT_CREATE, &ocfg, 0); + dpaa2_ethq->tc_index, flow_id, OPR_OPT_CREATE, &ocfg, 0); if (ret) { - DPAA2_PMD_ERR("Error setting opr: ret: %d", ret); + DPAA2_PMD_ERR("Failed(%d) to set opr of TC%d.flow.%d", + ret, dpaa2_ethq->tc_index, flow_id); return ret; } @@ -3390,13 +3389,18 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, cfg->user_context = (size_t)(dpaa2_ethq); ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, - dpaa2_ethq->tc_index, flow_id, options, cfg); + dpaa2_ethq->tc_index, flow_id, options, cfg); if (ret) { - DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); + DPAA2_PMD_ERR("Failed(%d) to set queue of TC%d.flow.%d", + ret, dpaa2_ethq->tc_index, flow_id); return ret; } rte_memcpy(&dpaa2_ethq->ev, &queue_conf->ev, sizeof(struct rte_event)); + dpaa2_ethq->ev.flow_id = flow_id; + dpaa2_ethq->ev.event_type = RTE_EVENT_TYPE_ETHDEV; + dpaa2_ethq->ev.op = RTE_EVENT_OP_NEW; + dpaa2_ethq->ev.queue_id = eth_rx_queue_id; return 0; } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 9ef6ee0e8c..d46fbd6d7d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -929,21 +929,17 @@ uint16_t dpaa2_dev_prefetch_rx_channel(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); uint16_t dpaa2_dev_rx_channel(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); -void dpaa2_dev_process_parallel_event(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev); -void dpaa2_dev_process_atomic_event(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev); -void dpaa2_dev_process_ordered_event(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev); + +void dpaa2_dev_process_parallel_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev); +void dpaa2_dev_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev); +void dpaa2_dev_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev); + uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); uint16_t dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 3e8fc29baa..d0d4536ab4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1201,23 +1201,16 @@ dpaa2_dev_prefetch_rx_channel(void *queue, struct rte_mbuf **bufs, } void __rte_hot -dpaa2_dev_process_parallel_event(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +dpaa2_dev_process_parallel_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { - rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) + - DPAA2_FD_PTA_SIZE + 16)); + struct qbman_swp *swp = dpio_dev->sw_portal; - ev->flow_id = rxq->ev.flow_id; - ev->sub_event_type = rxq->ev.sub_event_type; - ev->event_type = RTE_EVENT_TYPE_ETHDEV; - ev->op = RTE_EVENT_OP_NEW; - ev->sched_type = rxq->ev.sched_type; - ev->queue_id = rxq->ev.queue_id; - ev->priority = rxq->ev.priority; + if (dpaa2_svr_family != SVR_LX2160A) + dpaa2_dev_rx_annot_prefetch(fd); + ev->event = rxq->ev.event; if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); else @@ -1227,25 +1220,16 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, } void __rte_hot -dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +dpaa2_dev_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { uint8_t dqrr_index; - rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) + - DPAA2_FD_PTA_SIZE + 16)); - - ev->flow_id = rxq->ev.flow_id; - ev->sub_event_type = rxq->ev.sub_event_type; - ev->event_type = RTE_EVENT_TYPE_ETHDEV; - ev->op = RTE_EVENT_OP_NEW; - ev->sched_type = rxq->ev.sched_type; - ev->queue_id = rxq->ev.queue_id; - ev->priority = rxq->ev.priority; + if (dpaa2_svr_family != SVR_LX2160A) + dpaa2_dev_rx_annot_prefetch(fd); + ev->event = rxq->ev.event; if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); else @@ -1253,29 +1237,22 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; - DPAA2_PER_LCORE_DQRR_SIZE++; - DPAA2_PER_LCORE_DQRR_HELD |= UINT64_C(1) << dqrr_index; - DPAA2_PER_LCORE_DQRR_MBUF(dqrr_index) = ev->mbuf; + dpio_dev->dpaa2_held_bufs.dqrr_size++; + dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; + dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = ev->mbuf; } void __rte_hot -dpaa2_dev_process_ordered_event(struct qbman_swp *swp, - const struct qbman_fd *fd, - const struct qbman_result *dq, - struct dpaa2_queue *rxq, - struct rte_event *ev) +dpaa2_dev_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) { - rte_prefetch0((void *)(size_t)(DPAA2_GET_FD_ADDR(fd) + - DPAA2_FD_PTA_SIZE + 16)); + struct qbman_swp *swp = dpio_dev->sw_portal; - ev->flow_id = rxq->ev.flow_id; - ev->sub_event_type = rxq->ev.sub_event_type; - ev->event_type = RTE_EVENT_TYPE_ETHDEV; - ev->op = RTE_EVENT_OP_NEW; - ev->sched_type = rxq->ev.sched_type; - ev->queue_id = rxq->ev.queue_id; - ev->priority = rxq->ev.priority; + if (dpaa2_svr_family != SVR_LX2160A) + dpaa2_dev_rx_annot_prefetch(fd); + ev->event = rxq->ev.event; if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); else diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index e8e21e28cc..b28962c5f8 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -129,6 +129,8 @@ int rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off); +#define RTE_DPAA2_EVENT_PORT_CFG_ATOMIC RTE_BIT32(31) + /** RTE_DPAA2_MIX_GROUP_FLOW has same behavio as RTE_DPAA2_FLAT_GROUP_FLOW*/ enum rte_dpaa2_flow_type { RTE_DPAA2_FLAT_GROUP_FLOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 32/65] event/dpaa2: fix Tx adapter enqueue for mixed destinations 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (30 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 31/65] event/dpaa2: rework event port model and DPCI handling Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 33/65] event/dpaa2: rework self test for dynamic link and balance check Prashant Gupta ` (32 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The "same destination" Tx adapter enqueue path assumed every event in a burst targeted the same ethdev port and Tx queue, reading the port and queue id only from the first mbuf (ev[0]) and pushing the whole burst with rte_eth_tx_burst() to that single destination. This assumption does not always hold: an event burst may carry mbufs bound for different ports or queues. In that case, packets destined for other ports/queues were sent to the destination of the first mbuf, causing misdirected transmission. Make the generic enqueue handler, which resolves the port and Tx queue per mbuf and transmits through dpaa2_dev_tx_multi_txq_ordered(), the sole implementation. The same-destination variant now simply forwards to it, so both callbacks handle mixed destinations correctly. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 45 ++++++++-------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 03016d2a12..78a069b456 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -983,28 +983,28 @@ dpaa2_eventdev_tx_adapter_caps(const struct rte_eventdev *dev, } static uint16_t -dpaa2_eventdev_txa_enqueue_same_dest(void *port, +dpaa2_eventdev_txa_enqueue(void *port, struct rte_event ev[], uint16_t nb_events) { - struct rte_mbuf *m[MAX_TX_RING_SLOTS], *m0; - uint16_t sent = 0, burst, i, port_id; - uint8_t qid; + void *txq[MAX_TX_RING_SLOTS]; + struct rte_mbuf *m[MAX_TX_RING_SLOTS]; + uint16_t sent = 0, burst, i, port_id, qid; RTE_SET_USED(port); - m0 = ev[0].mbuf; - qid = rte_event_eth_tx_adapter_txq_get(m0); - port_id = m0->port; - /* The advertised enqueue depth is the EQCR size, which may exceed the * on-stack burst array, so transmit in ring-sized chunks. */ while (sent < nb_events) { burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); - for (i = 0; i < burst; i++) + for (i = 0; i < burst; i++) { m[i] = ev[sent + i].mbuf; + port_id = m[i]->port; + qid = rte_event_eth_tx_adapter_txq_get(m[i]); + txq[i] = rte_eth_devices[port_id].data->tx_queues[qid]; + } - i = rte_eth_tx_burst(port_id, qid, m, burst); + i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); sent += i; if (i < burst) break; @@ -1014,31 +1014,10 @@ dpaa2_eventdev_txa_enqueue_same_dest(void *port, } static uint16_t -dpaa2_eventdev_txa_enqueue(void *port, +dpaa2_eventdev_txa_enqueue_same_dest(void *port, struct rte_event ev[], uint16_t nb_events) { - void *txq[MAX_TX_RING_SLOTS]; - struct rte_mbuf *m[MAX_TX_RING_SLOTS]; - uint16_t sent = 0, burst, i; - uint8_t qid; - - RTE_SET_USED(port); - - while (sent < nb_events) { - burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); - for (i = 0; i < burst; i++) { - m[i] = ev[sent + i].mbuf; - qid = rte_event_eth_tx_adapter_txq_get(m[i]); - txq[i] = rte_eth_devices[m[i]->port].data->tx_queues[qid]; - } - - i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); - sent += i; - if (i < burst) - break; - } - - return sent; + return dpaa2_eventdev_txa_enqueue(port, ev, nb_events); } static struct eventdev_ops dpaa2_eventdev_ops = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 33/65] event/dpaa2: rework self test for dynamic link and balance check 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (31 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 32/65] event/dpaa2: fix Tx adapter enqueue for mixed destinations Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 34/65] event/dpaa2: add DPCON based standalone Rx scheduler Prashant Gupta ` (31 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The eventdev self test linked every queue to every port during device setup, which prevented individual test cases from exercising their own queue-to-port topologies and made enqueue/dequeue accounting unreliable. Rework the self test as follows: - Move queue-to-port linking out of _eventdev_setup() into each test case, so every test establishes the link topology it needs. - Convert the test mode selector to a bitmask and add an atomic port setup path (RTE_DPAA2_EVENT_PORT_CFG_ATOMIC), used by the multi-queue/multi-port dequeue test. - Return the number of dequeued events from consume_events() and assert that the dequeued count matches the injected count, verifying balance between ingress and egress. - Retry enqueue until the event is accepted so injection no longer silently drops events. - Propagate meaningful error codes (-ENOMEM, -EINVAL, -ETIMEDOUT, -ENODEV, and the underlying ret) instead of a bare -1. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev_selftest.c | 336 ++++++++++-------- 1 file changed, 197 insertions(+), 139 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev_selftest.c b/drivers/event/dpaa2/dpaa2_eventdev_selftest.c index 2c688bd194..569621dc39 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev_selftest.c +++ b/drivers/event/dpaa2/dpaa2_eventdev_selftest.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP + * Copyright 2018-2019, 2026 NXP */ #include <rte_stdatomic.h> @@ -20,6 +20,7 @@ #include <bus_vdev_driver.h> #include <rte_test.h> #include <bus_fslmc_driver.h> +#include <rte_pmd_dpaa2.h> #include "dpaa2_eventdev.h" #include "dpaa2_eventdev_logs.h" @@ -105,63 +106,64 @@ devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf, } enum { - TEST_EVENTDEV_SETUP_DEFAULT, - TEST_EVENTDEV_SETUP_PRIORITY, - TEST_EVENTDEV_SETUP_DEQUEUE_TIMEOUT, + TEST_EVENTDEV_SETUP_DEFAULT = (1 << 0), + TEST_EVENTDEV_SETUP_PRIORITY = (1 << 1), + TEST_EVENTDEV_SETUP_DEQUEUE_TIMEOUT = (1 << 2), + TEST_EVENTDEV_SETUP_ATOMIC = (1 << 3) }; static int _eventdev_setup(int mode) { - int i, ret; + int ret; struct rte_event_dev_config dev_conf; struct rte_event_dev_info info; const char *pool_name = "evdev_dpaa2_test_pool"; + uint32_t queue_count, port_count, i; + uint8_t step; + struct rte_event_port_conf port_conf, *pport_conf; /* Create and destroy pool for each test case to make it standalone */ eventdev_test_mempool = rte_pktmbuf_pool_create(pool_name, - MAX_EVENTS, + 1024 /*TOTAL_EVENTS*/, 0 /*MBUF_CACHE_SIZE*/, 0, - 512, /* Use very small mbufs */ + 2048 + 256 /*512*/, /* Use very small mbufs */ rte_socket_id()); if (!eventdev_test_mempool) { dpaa2_evdev_err("ERROR creating mempool"); - return -1; + return -ENOMEM; } ret = rte_event_dev_info_get(evdev, &info); RTE_TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info"); RTE_TEST_ASSERT(info.max_num_events >= (int32_t)MAX_EVENTS, "ERROR max_num_events=%d < max_events=%d", - info.max_num_events, MAX_EVENTS); + info.max_num_events, MAX_EVENTS); devconf_set_default_sane_values(&dev_conf, &info); - if (mode == TEST_EVENTDEV_SETUP_DEQUEUE_TIMEOUT) + if (mode & TEST_EVENTDEV_SETUP_DEQUEUE_TIMEOUT) dev_conf.event_dev_cfg |= RTE_EVENT_DEV_CFG_PER_DEQUEUE_TIMEOUT; ret = rte_event_dev_configure(evdev, &dev_conf); RTE_TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev"); - uint32_t queue_count; RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_QUEUE_COUNT, - &queue_count), "Queue count get failed"); - - if (mode == TEST_EVENTDEV_SETUP_PRIORITY) { - if (queue_count > 8) { - dpaa2_evdev_err( - "test expects the unique priority per queue"); - return -ENOTSUP; + RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count), + "Queue count get failed"); + + if (mode & TEST_EVENTDEV_SETUP_PRIORITY) { + if (!queue_count) { + dpaa2_evdev_err("No queue available"); + return -EINVAL; } /* Configure event queues(0 to n) with * RTE_EVENT_DEV_PRIORITY_HIGHEST to * RTE_EVENT_DEV_PRIORITY_LOWEST */ - uint8_t step = (RTE_EVENT_DEV_PRIORITY_LOWEST + 1) / - queue_count; - for (i = 0; i < (int)queue_count; i++) { + step = (RTE_EVENT_DEV_PRIORITY_LOWEST + 1) / queue_count; + for (i = 0; i < queue_count; i++) { struct rte_event_queue_conf queue_conf; ret = rte_event_queue_default_conf_get(evdev, i, @@ -170,29 +172,33 @@ _eventdev_setup(int mode) i); queue_conf.priority = i * step; ret = rte_event_queue_setup(evdev, i, &queue_conf); - RTE_TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d", - i); + RTE_TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d", i); } - } else { /* Configure event queues with default priority */ - for (i = 0; i < (int)queue_count; i++) { + for (i = 0; i < queue_count; i++) { ret = rte_event_queue_setup(evdev, i, NULL); - RTE_TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d", - i); + RTE_TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d", i); } } + /* Configure event ports */ - uint32_t port_count; RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_PORT_COUNT, - &port_count), "Port count get failed"); - for (i = 0; i < (int)port_count; i++) { - ret = rte_event_port_setup(evdev, i, NULL); + RTE_EVENT_DEV_ATTR_PORT_COUNT, &port_count), + "Port count get failed"); + for (i = 0; i < port_count; i++) { + if (mode & TEST_EVENTDEV_SETUP_ATOMIC) { + pport_conf = &port_conf; + memset(pport_conf, 0, sizeof(struct rte_event_port_conf)); + ret = rte_event_port_default_conf_get(evdev, i, pport_conf); + RTE_TEST_ASSERT_SUCCESS(ret, + "Failed to get default conf of port=%d", i); + pport_conf->event_port_cfg = RTE_DPAA2_EVENT_PORT_CFG_ATOMIC; + } else { + pport_conf = NULL; + } + ret = rte_event_port_setup(evdev, i, pport_conf); RTE_TEST_ASSERT_SUCCESS(ret, "Failed to setup port=%d", i); - ret = rte_event_port_link(evdev, i, NULL, NULL, 0); - RTE_TEST_ASSERT(ret >= 0, "Failed to link all queues port=%d", - i); } ret = rte_event_dev_start(evdev); @@ -207,6 +213,13 @@ eventdev_setup(void) return _eventdev_setup(TEST_EVENTDEV_SETUP_DEFAULT); } +static int +eventdev_atomic_port_setup(void) +{ + return _eventdev_setup(TEST_EVENTDEV_SETUP_DEFAULT | + TEST_EVENTDEV_SETUP_ATOMIC); +} + static void eventdev_teardown(void) { @@ -216,9 +229,9 @@ eventdev_teardown(void) static void update_event_and_validation_attr(struct rte_mbuf *m, struct rte_event *ev, - uint32_t flow_id, uint8_t event_type, - uint8_t sub_event_type, uint8_t sched_type, - uint8_t queue, uint8_t port, uint8_t seq) + uint32_t flow_id, uint8_t event_type, + uint8_t sub_event_type, uint8_t sched_type, + uint8_t queue, uint8_t port, uint8_t seq) { struct event_attr *attr; @@ -249,6 +262,7 @@ inject_events(uint32_t flow_id, uint8_t event_type, uint8_t sub_event_type, { struct rte_mbuf *m; unsigned int i; + uint16_t eq, err_count; for (i = 0; i < events; i++) { struct rte_event ev = {.event = 0, .u64 = 0}; @@ -258,7 +272,16 @@ inject_events(uint32_t flow_id, uint8_t event_type, uint8_t sub_event_type, update_event_and_validation_attr(m, &ev, flow_id, event_type, sub_event_type, sched_type, queue, port, i); - rte_event_enqueue_burst(evdev, port, &ev, 1); + err_count = 0; +eq_again: + eq = rte_event_enqueue_burst(evdev, port, &ev, 1); + if (eq != 1) { + dpaa2_evdev_err("Failed, eq(%d) != 1", eq); + if (err_count > 10) + return -EBUSY; + err_count++; + goto eq_again; + } } return 0; } @@ -271,7 +294,7 @@ check_excess_events(uint8_t port) struct rte_event ev; /* Check for excess events, try for a few times and exit */ - for (i = 0; i < 32; i++) { + for (i = 0; i < 4; i++) { valid_event = rte_event_dequeue_burst(evdev, port, &ev, 1, 0); RTE_TEST_ASSERT_SUCCESS(valid_event, @@ -285,27 +308,35 @@ static int generate_random_events(const unsigned int total_events) { struct rte_event_dev_info info; - unsigned int i; + uint32_t queue_count, i; + uint8_t queues[RTE_EVENT_MAX_QUEUES_PER_DEV]; int ret; - uint32_t queue_count; RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_QUEUE_COUNT, - &queue_count), "Queue count get failed"); + RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count), + "Queue count get failed"); + if (queue_count > RTE_EVENT_MAX_QUEUES_PER_DEV) + queue_count = RTE_EVENT_MAX_QUEUES_PER_DEV; + for (i = 0; i < queue_count; i++) + queues[i] = i; + + ret = rte_event_port_link(evdev, 0, queues, NULL, + queue_count); + RTE_TEST_ASSERT(ret >= 0, "Failed to link %d queues port0", + queue_count); ret = rte_event_dev_info_get(evdev, &info); RTE_TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info"); for (i = 0; i < total_events; i++) { - ret = inject_events( - rte_rand() % info.max_event_queue_flows /*flow_id */, + ret = inject_events(rte_rand() % info.max_event_queue_flows /*flow_id */, RTE_EVENT_TYPE_CPU /* event_type */, rte_rand() % 256 /* sub_event_type */, rte_rand() % (RTE_SCHED_TYPE_PARALLEL + 1), - rte_rand() % queue_count /* queue */, + rte_rand() % queue_count, 0 /* port */, 1 /* events */); if (ret) - return -1; + return ret; } return ret; } @@ -339,7 +370,8 @@ typedef int (*validate_event_cb)(uint32_t index, uint8_t port, struct rte_event *ev); static int -consume_events(uint8_t port, const uint32_t total_events, validate_event_cb fn) +consume_events(uint8_t port, const uint32_t total_events, + uint32_t *dq_events, validate_event_cb fn) { int ret; uint16_t valid_event; @@ -349,7 +381,7 @@ consume_events(uint8_t port, const uint32_t total_events, validate_event_cb fn) while (1) { if (++forward_progress_cnt > UINT16_MAX) { dpaa2_evdev_err("Detected deadlock"); - return -1; + return -ETIMEDOUT; } valid_event = rte_event_dequeue_burst(evdev, port, &ev, 1, 0); @@ -359,9 +391,9 @@ consume_events(uint8_t port, const uint32_t total_events, validate_event_cb fn) forward_progress_cnt = 0; ret = validate_event(&ev); if (ret) - return -1; + return ret; - if (fn != NULL) { + if (fn) { ret = fn(index, port, &ev); RTE_TEST_ASSERT_SUCCESS(ret, "Failed to validate test specific event"); @@ -374,6 +406,9 @@ consume_events(uint8_t port, const uint32_t total_events, validate_event_cb fn) break; } + if (dq_events) + *dq_events = events; + return check_excess_events(port); } @@ -394,18 +429,28 @@ static int test_simple_enqdeq(uint8_t sched_type) { int ret; + uint8_t queue = 0; + uint32_t total_dq = 0; + + ret = rte_event_port_link(evdev, 0, &queue, NULL, 1); + RTE_TEST_ASSERT(ret >= 0, "Failed to link 1 queues port0"); ret = inject_events(0 /*flow_id */, - RTE_EVENT_TYPE_CPU /* event_type */, - 0 /* sub_event_type */, - sched_type, - 0 /* queue */, - 0 /* port */, - MAX_EVENTS); + RTE_EVENT_TYPE_CPU /* event_type */, + 0 /* sub_event_type */, + sched_type, + 0 /* queue */, + 0 /* port */, + MAX_EVENTS); if (ret) - return -1; + return ret; - return consume_events(0 /* port */, MAX_EVENTS, validate_simple_enqdeq); + ret = consume_events(0/* port */, MAX_EVENTS, &total_dq, validate_simple_enqdeq); + RTE_TEST_ASSERT(!ret, "Failed to consume event from port0"); + RTE_TEST_ASSERT(total_dq == MAX_EVENTS, + "total_dq(%d) != MAX_EVENTS(8)", total_dq); + + return ret; } static int @@ -429,12 +474,18 @@ static int test_multi_queue_enq_single_port_deq(void) { int ret; + uint32_t dq_events; ret = generate_random_events(MAX_EVENTS); if (ret) - return -1; + return ret; + + ret = consume_events(0/* port */, MAX_EVENTS, &dq_events, NULL); + RTE_TEST_ASSERT(!ret, "Failed to consume event from port0"); + RTE_TEST_ASSERT(dq_events == MAX_EVENTS, + "dq_events(%d) != MAX_EVENTS(8)", dq_events); - return consume_events(0 /* port */, MAX_EVENTS, NULL); + return ret; } static int @@ -479,8 +530,7 @@ wait_workers_to_join(int lcore, const __rte_atomic uint32_t *count) print_cycles = new_cycles; } if (new_cycles - cycles > rte_get_timer_hz() * 10) { - dpaa2_evdev_info( - "%s: No schedules for seconds, deadlock (%u)", + dpaa2_evdev_info("%s: No schedules for seconds, deadlock (%d)", __func__, rte_atomic_load_explicit(count, rte_memory_order_relaxed)); rte_event_dev_dump(evdev, stdout); @@ -495,8 +545,8 @@ wait_workers_to_join(int lcore, const __rte_atomic uint32_t *count) static int launch_workers_and_wait(int (*main_worker)(void *), - int (*workers)(void *), uint32_t total_events, - uint8_t nb_workers, uint8_t sched_type) + int (*workers)(void *), uint32_t total_events, + uint8_t nb_workers, uint8_t sched_type) { uint8_t port = 0; int w_lcore; @@ -513,13 +563,13 @@ launch_workers_and_wait(int (*main_worker)(void *), param = malloc(sizeof(struct test_core_param) * nb_workers); if (!param) - return -1; + return -ENOMEM; ret = rte_event_dequeue_timeout_ticks(evdev, rte_rand() % 10000000/* 10ms */, &dequeue_tmo_ticks); if (ret) { free(param); - return -1; + return ret; } param[0].total_events = &atomic_total_events; @@ -563,22 +613,22 @@ test_multi_queue_enq_multi_port_deq(void) ret = generate_random_events(total_events); if (ret) - return -1; + return ret; RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_PORT_COUNT, - &nr_ports), "Port count get failed"); + RTE_EVENT_DEV_ATTR_PORT_COUNT, &nr_ports), + "Port count get failed"); nr_ports = RTE_MIN(nr_ports, rte_lcore_count() - 1); if (!nr_ports) { dpaa2_evdev_err("%s: Not enough ports=%d or workers=%d", - __func__, nr_ports, rte_lcore_count() - 1); - return 0; + __func__, nr_ports, rte_lcore_count() - 1); + return -EINVAL; } return launch_workers_and_wait(worker_multi_port_fn, - worker_multi_port_fn, total_events, - nr_ports, 0xff /* invalid */); + worker_multi_port_fn, total_events, + nr_ports, 0xff /* invalid */); } static @@ -589,7 +639,6 @@ void flush(uint8_t dev_id, struct rte_event event, void *arg) RTE_SET_USED(dev_id); if (event.event_type == RTE_EVENT_TYPE_CPU) *count = *count + 1; - } static int @@ -610,8 +659,8 @@ test_dev_stop_flush(void) if (ret) return -3; RTE_TEST_ASSERT_EQUAL(total_events, count, - "count mismatch total_events=%d count=%d", - total_events, count); + "count mismatch total_events=%d count=%d", + total_events, count); return 0; } @@ -621,8 +670,8 @@ validate_queue_to_port_single_link(uint32_t index, uint8_t port, { RTE_SET_USED(index); RTE_TEST_ASSERT_EQUAL(port, ev->queue_id, - "queue mismatch enq=%d deq =%d", - port, ev->queue_id); + "queue mismatch enq=%d deq =%d", + port, ev->queue_id); return 0; } @@ -633,39 +682,32 @@ validate_queue_to_port_single_link(uint32_t index, uint8_t port, static int test_queue_to_port_single_link(void) { - int i, nr_links, ret; - - uint32_t port_count; + int ret; + uint8_t queue; + uint32_t port_count, queue_count, nr_links, total_events, i; + uint32_t dq_events = 0, total_dqs = 0; RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_PORT_COUNT, - &port_count), "Port count get failed"); - - /* Unlink all connections that created in eventdev_setup */ - for (i = 0; i < (int)port_count; i++) { - ret = rte_event_port_unlink(evdev, i, NULL, 0); - RTE_TEST_ASSERT(ret >= 0, - "Failed to unlink all queues port=%d", i); - } - - uint32_t queue_count; + RTE_EVENT_DEV_ATTR_PORT_COUNT, &port_count), + "Port count get failed"); RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_QUEUE_COUNT, - &queue_count), "Queue count get failed"); + RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count), + "Queue count get failed"); nr_links = RTE_MIN(port_count, queue_count); - const unsigned int total_events = MAX_EVENTS / nr_links; + total_events = MAX_EVENTS / nr_links; - /* Link queue x to port x and inject events to queue x through port x */ for (i = 0; i < nr_links; i++) { - uint8_t queue = (uint8_t)i; - + queue = i; ret = rte_event_port_link(evdev, i, &queue, NULL, 1); RTE_TEST_ASSERT(ret == 1, "Failed to link queue to port %d", i); + } - ret = inject_events( - 0x100 /*flow_id */, + /* Link queue x to port x and inject events to queue x through port x */ + for (i = 0; i < nr_links; i++) { + queue = i; + ret = inject_events(0x100 /*flow_id */, RTE_EVENT_TYPE_CPU /* event_type */, rte_rand() % 256 /* sub_event_type */, rte_rand() % (RTE_SCHED_TYPE_PARALLEL + 1), @@ -673,16 +715,21 @@ test_queue_to_port_single_link(void) i /* port */, total_events /* events */); if (ret) - return -1; + return ret; } /* Verify the events generated from correct queue */ for (i = 0; i < nr_links; i++) { ret = consume_events(i /* port */, total_events, + &dq_events, validate_queue_to_port_single_link); if (ret) - return -1; + return ret; + total_dqs += dq_events; } + RTE_TEST_ASSERT(total_dqs == total_events * nr_links, + "total_dqs(%d) != total_events(%d) * nr_links(%d)", + total_dqs, total_events, nr_links); return 0; } @@ -693,8 +740,8 @@ validate_queue_to_port_multi_link(uint32_t index, uint8_t port, { RTE_SET_USED(index); RTE_TEST_ASSERT_EQUAL(port, (ev->queue_id & 0x1), - "queue mismatch enq=%d deq =%d", - port, ev->queue_id); + "queue mismatch enq=%d deq =%d", + port, ev->queue_id); return 0; } @@ -705,46 +752,48 @@ validate_queue_to_port_multi_link(uint32_t index, uint8_t port, static int test_queue_to_port_multi_link(void) { - int ret, port0_events = 0, port1_events = 0; + int ret; uint8_t queue, port; - uint32_t nr_queues = 0; - uint32_t nr_ports = 0; + uint32_t nr_queues = 0, total_events, even_idx = 0, odd_idx = 0; + uint32_t nr_ports = 0, dq_events, port0_events = 0, port1_events = 0; + uint8_t even_queues[RTE_EVENT_MAX_QUEUES_PER_DEV]; + uint8_t odd_queues[RTE_EVENT_MAX_QUEUES_PER_DEV]; RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_QUEUE_COUNT, - &nr_queues), "Queue count get failed"); - + RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &nr_queues), + "Queue count get failed"); RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_QUEUE_COUNT, - &nr_queues), "Queue count get failed"); - RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, - RTE_EVENT_DEV_ATTR_PORT_COUNT, - &nr_ports), "Port count get failed"); + RTE_EVENT_DEV_ATTR_PORT_COUNT, &nr_ports), + "Port count get failed"); if (nr_ports < 2) { dpaa2_evdev_err("%s: Not enough ports to test ports=%d", - __func__, nr_ports); - return 0; + __func__, nr_ports); + return -ENODEV; } - /* Unlink all connections that created in eventdev_setup */ - for (port = 0; port < nr_ports; port++) { - ret = rte_event_port_unlink(evdev, port, NULL, 0); - RTE_TEST_ASSERT(ret >= 0, "Failed to unlink all queues port=%d", - port); + for (queue = 0; queue < nr_queues; queue++) { + if (queue & 0x1) { + odd_queues[odd_idx] = queue; + odd_idx++; + } else { + even_queues[even_idx] = queue; + even_idx++; + } } - const unsigned int total_events = MAX_EVENTS / nr_queues; + ret = rte_event_port_link(evdev, 0, even_queues, NULL, even_idx); + RTE_TEST_ASSERT(ret >= 0, "Failed to link queues port0"); + ret = rte_event_port_link(evdev, 1, odd_queues, NULL, odd_idx); + RTE_TEST_ASSERT(ret >= 0, "Failed to link queues port1"); + + total_events = MAX_EVENTS / nr_queues; /* Link all even number of queues to port0 and odd numbers to port 1*/ for (queue = 0; queue < nr_queues; queue++) { port = queue & 0x1; - ret = rte_event_port_link(evdev, port, &queue, NULL, 1); - RTE_TEST_ASSERT(ret == 1, "Failed to link queue=%d to port=%d", - queue, port); - ret = inject_events( - 0x100 /*flow_id */, + ret = inject_events(0x100 /*flow_id */, RTE_EVENT_TYPE_CPU /* event_type */, rte_rand() % 256 /* sub_event_type */, rte_rand() % (RTE_SCHED_TYPE_PARALLEL + 1), @@ -752,7 +801,7 @@ test_queue_to_port_multi_link(void) port /* port */, total_events /* events */); if (ret) - return -1; + return ret; if (port == 0) port0_events += total_events; @@ -760,14 +809,23 @@ test_queue_to_port_multi_link(void) port1_events += total_events; } - ret = consume_events(0 /* port */, port0_events, - validate_queue_to_port_multi_link); + dq_events = 0; + ret = consume_events(0/* port */, port0_events, &dq_events, + validate_queue_to_port_multi_link); if (ret) - return -1; - ret = consume_events(1 /* port */, port1_events, - validate_queue_to_port_multi_link); + return ret; + RTE_TEST_ASSERT(dq_events == port0_events, + "dq_events(%d) != port0_events(%d)", + dq_events, port0_events); + + dq_events = 0; + ret = consume_events(1/* port */, port1_events, &dq_events, + validate_queue_to_port_multi_link); if (ret) - return -1; + return ret; + RTE_TEST_ASSERT(dq_events == port1_events, + "dq_events(%d) != port1_events(%d)", + dq_events, port0_events); return 0; } @@ -805,7 +863,7 @@ test_eventdev_dpaa2(void) test_multi_queue_enq_single_port_deq); DPAA2_TEST_RUN(eventdev_setup, eventdev_teardown, test_dev_stop_flush); - DPAA2_TEST_RUN(eventdev_setup, eventdev_teardown, + DPAA2_TEST_RUN(eventdev_atomic_port_setup, eventdev_teardown, test_multi_queue_enq_multi_port_deq); DPAA2_TEST_RUN(eventdev_setup, eventdev_teardown, test_queue_to_port_single_link); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 34/65] event/dpaa2: add DPCON based standalone Rx scheduler 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (32 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 33/65] event/dpaa2: rework self test for dynamic link and balance check Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 35/65] event/dpaa2: add push mode to DPCON " Prashant Gupta ` (30 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add a standalone DPCON-based Rx scheduler API that lets applications aggregate multiple ethdev Rx queues onto a single DPCON channel and receive packets directly, without going through the eventdev framework. The new API is exposed as experimental in rte_pmd_dpaa2.h: - rte_dpaa2_scheduler_init(): allocate a DPCON device and select the receive path (plain or prefetch, chosen by the DPAA2_SCHEDULE_RX_PREFETCH env). - rte_dpaa2_scheduler_add(): attach an ethdev Rx queue to the DPCON channel with a given priority. - rte_dpaa2_scheduler_start(): enable the DPCON channel. - rte_dpaa2_scheduler_rx(): dequeue packets from the channel. - rte_dpaa2_scheduler_destroy(): disable the DPCON channel. - rte_dpaa2_scheduler_max_prio(): Get the maximum supported priority. The priority specified in rte_dpaa2_scheduler_add() must not exceed this value. Two receive implementations are provided: a plain single-buffer pull (dpaa2_scheduler_recv) and a double-buffered prefetch variant (dpaa2_scheduler_prefetch_recv) that overlaps the next pull with mbuf extraction. To support this, the fslmc bus exposes internal helpers rte_dpaa2_dpcon_start()/stop() to enable/disable a DPCON, extends struct dpaa2_dpcon_dev with per-lcore dequeue storage and an rx_schedule callback, and caches the dequeue storage IOVA in struct queue_storage_info_t to avoid repeated address translation on the receive path. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpcon.c | 25 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 2 + drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 5 + drivers/event/dpaa2/dpaa2_scheduler.c | 458 ++++++++++++++++++++++ drivers/event/dpaa2/meson.build | 3 +- drivers/net/dpaa2/dpaa2_ethdev.c | 4 +- drivers/net/dpaa2/dpaa2_ethdev.h | 38 ++ drivers/net/dpaa2/dpaa2_rxtx.c | 21 + drivers/net/dpaa2/rte_pmd_dpaa2.h | 28 ++ 9 files changed, 579 insertions(+), 5 deletions(-) create mode 100644 drivers/event/dpaa2/dpaa2_scheduler.c diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpcon.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpcon.c index eff8bc2445..400fb35c46 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpcon.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpcon.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2017, 2020, 2023 NXP + * Copyright 2017, 2020, 2023, 2026 NXP * */ @@ -121,6 +121,29 @@ void rte_dpaa2_free_dpcon_dev(struct dpaa2_dpcon_dev *dpcon) } } +RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_dpcon_start) +int32_t rte_dpaa2_dpcon_start(struct dpaa2_dpcon_dev *dpcon_dev) +{ + int32_t ret; + + ret = dpcon_enable(&dpcon_dev->dpcon, CMD_PRI_LOW, dpcon_dev->token); + if (ret) + DPAA2_BUS_ERR("Failed(%d) to enable dpcon.%d", ret, dpcon_dev->dpcon_id); + + return ret; +} + +RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_dpcon_stop) +int32_t rte_dpaa2_dpcon_stop(struct dpaa2_dpcon_dev *dpcon_dev) +{ + int32_t ret; + + ret = dpcon_disable(&dpcon_dev->dpcon, CMD_PRI_LOW, dpcon_dev->token); + if (ret) + DPAA2_BUS_ERR("Failed(%d) to disable dpcon.%d", ret, dpcon_dev->dpcon_id); + + return ret; +} static void rte_dpaa2_close_dpcon_device(int object_id) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index e88334088b..55dcef41d1 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -692,6 +692,8 @@ dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage) RTE_CACHE_LINE_SIZE); if (!q_storage->dq_storage[i]) goto fail; + q_storage->iova_dq_storage[i] = + DPAA2_VADDR_TO_IOVA(q_storage->dq_storage[i]); } return 0; fail: diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f80abffb40..b00e52a9b7 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -152,6 +152,7 @@ struct dpaa2_dpbp_dev { struct queue_storage_info_t { struct qbman_result *dq_storage[NUM_DQS_PER_QUEUE]; + uint64_t iova_dq_storage[NUM_DQS_PER_QUEUE]; struct qbman_result *active_dqs; uint8_t active_dpio_id; uint8_t toggle; @@ -297,6 +298,10 @@ __rte_internal struct dpaa2_dpcon_dev *rte_dpaa2_alloc_dpcon_dev(void); __rte_internal void rte_dpaa2_free_dpcon_dev(struct dpaa2_dpcon_dev *dpcon); +__rte_internal +int32_t rte_dpaa2_dpcon_start(struct dpaa2_dpcon_dev *dpcon_dev); +__rte_internal +int32_t rte_dpaa2_dpcon_stop(struct dpaa2_dpcon_dev *dpcon_dev); /* Refer to Table 7-3 in SEC BG */ #define QBMAN_FLE_WORD4_FMT_SBF 0x0 /* Single buffer frame */ diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c b/drivers/event/dpaa2/dpaa2_scheduler.c new file mode 100644 index 0000000000..e553c4d3f6 --- /dev/null +++ b/drivers/event/dpaa2/dpaa2_scheduler.c @@ -0,0 +1,458 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2026 NXP + */ + +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <errno.h> + +#include <rte_malloc.h> +#include <rte_memcpy.h> +#include <rte_string_fns.h> +#include <rte_cycles.h> +#include <rte_kvargs.h> +#include <eal_export.h> +#include <dev_driver.h> +#include <ethdev_driver.h> +#include <rte_event_eth_rx_adapter.h> + +#include <bus_fslmc_driver.h> +#include <mc/fsl_dpcon.h> +#include <portal/dpaa2_hw_pvt.h> +#include <dpaa2_hw_dpio.h> +#include <compat.h> +#include "dpaa2_ethdev.h" +#include "dpaa2_eventdev.h" +#include "dpaa2_eventdev_logs.h" +#include "rte_pmd_dpaa2.h" + +#define DPAA2_SCH_PORT_QUEUE_MAX_NUM 64 +struct dpaa2_sch_port_queue { + struct rte_eth_dev *eth_dev; + uint16_t port_id; + uint16_t rxq_id; + uint8_t priority; + struct rte_event_eth_rx_adapter_queue_conf queue_conf; + int configured; +}; + +struct dpaa2_sch_dev { + struct dpaa2_dpcon_dev *dpcon_dev; + struct dpaa2_sch_port_queue port_queue[DPAA2_SCH_PORT_QUEUE_MAX_NUM]; + uint8_t port_queue_num; + struct queue_storage_info_t q_storage[RTE_MAX_LCORE]; + uint16_t (*rx_schedule)(struct dpaa2_sch_dev *dev, + struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +}; + +static int +dpaa2_scheduler_dq_storage_init(struct dpaa2_sch_dev *sch_dev) +{ + int i, ret = 0; + + memset(&sch_dev->q_storage, 0, + sizeof(struct queue_storage_info_t) * RTE_MAX_LCORE); + + for (i = 0; i < RTE_MAX_LCORE; i++) { + ret = dpaa2_alloc_dq_storage(&sch_dev->q_storage[i]); + if (ret) + goto err; + } + return 0; +err: + for (i = 0; i < RTE_MAX_LCORE; i++) + dpaa2_free_dq_storage(&sch_dev->q_storage[i]); + + return ret; +} + +static inline void +dpaa2_qbman_pull_desc_channel_set(struct qbman_pull_desc *pulldesc, + uint32_t num, uint16_t ch_id, struct qbman_result *dq_sch_storage, + uint64_t iova_storage) +{ + qbman_pull_desc_clear(pulldesc); + qbman_pull_desc_set_numframes(pulldesc, num); + qbman_pull_desc_set_channel(pulldesc, ch_id, + qbman_pull_type_prio); + qbman_pull_desc_set_storage(pulldesc, dq_sch_storage, + iova_storage, 1); +} + +static uint16_t +dpaa2_scheduler_recv(struct dpaa2_sch_dev *sch_dev, + struct rte_mbuf **mbuf, uint16_t nb_pkts) +{ + struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev; + uint16_t ch_id = dpcon_dev->qbman_ch_id; + struct qbman_result *dq_sch_storage; + uint16_t total_nb_pkts = nb_pkts; + struct qbman_pull_desc pulldesc; + const struct qbman_fd *fd; + struct dpaa2_queue *rvq; + bool is_last, next_pull; + int ret, rcvd_pkts = 0; + struct qbman_swp *swp; + uint8_t status; + struct queue_storage_info_t *q_storage; + uint64_t iova_storage; + struct dpaa2_dev_priv *priv; + + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); + if (ret) { + DPAA2_EVENTDEV_ERR("Failure(%d) in affining portal", ret); + return 0; + } + } + swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + q_storage = &sch_dev->q_storage[rte_lcore_id()]; + dq_sch_storage = q_storage->dq_storage[0]; + iova_storage = q_storage->iova_dq_storage[0]; + + do { + is_last = false; + next_pull = false; + dpaa2_qbman_pull_desc_channel_set(&pulldesc, nb_pkts, ch_id, + dq_sch_storage, iova_storage); + + while (1) { + if (qbman_swp_pull(swp, &pulldesc)) { + DPAA2_EVENTDEV_DEBUG("Line(%d): QBMAN is busy", __LINE__); + /* Portal was busy, try again */ + continue; + } + break; + } + /* Receive the packets till Last Dequeue entry is found with + * respect to the above issues PULL command. + */ + while (!is_last) { + /* Loop until the dq_storage is updated with + * new result by QBMAN + */ + while (!qbman_result_has_new_result(swp, dq_sch_storage)) + ; + + /* Check whether Last Pull command is Expired and + * setting Condition for Loop termination + */ + if (qbman_result_DQ_is_pull_complete(dq_sch_storage)) { + is_last = true; + /* Check for valid frame. */ + status = qbman_result_DQ_flags(dq_sch_storage); + if (unlikely(!(status & QBMAN_DQ_STAT_VALIDFRAME))) { + next_pull = true; + DPAA2_EVENTDEV_DEBUG("No frame is delivered"); + break; + } + nb_pkts = total_nb_pkts - (rcvd_pkts + 1); + if (!nb_pkts) + next_pull = true; + } + + fd = qbman_result_DQ_fd(dq_sch_storage); + rvq = (void *)qbman_result_DQ_fqd_ctx(dq_sch_storage); + priv = rvq->eth_data->dev_private; + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + mbuf[rcvd_pkts] = dpaa2_eth_sg_fd_to_mbuf_export(priv, fd); + else + mbuf[rcvd_pkts] = dpaa2_eth_fd_to_mbuf_export(priv, fd); + dpaa2_dev_rx_mbuf_flc_offload_export(mbuf[rcvd_pkts], fd); + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf[rcvd_pkts]); + rcvd_pkts++; + dq_sch_storage++; + iova_storage += sizeof(struct qbman_result); + } + } while (!next_pull); + /* End of Packet Rx loop */ + DPAA2_EVENTDEV_DEBUG("DPCONC Received %d Packets", rcvd_pkts); + + return rcvd_pkts; +} + +static uint16_t +dpaa2_scheduler_prefetch_recv(struct dpaa2_sch_dev *sch_dev, + struct rte_mbuf **mbuf, uint16_t nb_pkts) +{ + struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev; + uint16_t ch_id = dpcon_dev->qbman_ch_id, pull_size; + struct qbman_result *dq_storage, *dq_storage1 = NULL, *active; + struct qbman_pull_desc pulldesc; + struct queue_storage_info_t *q_storage; + uint64_t iova_storage; + const struct qbman_fd *fd; + struct dpaa2_queue *rvq; + int ret, rcvd_pkts = 0; + struct qbman_swp *swp; + struct dpaa2_dpio_dev *ethrx_dpio_dev; + uint8_t status, pending; + struct dpaa2_dev_priv *priv; + + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); + if (ret) { + DPAA2_EVENTDEV_ERR("Failure(%d) in affining portal", ret); + return 0; + } + } + swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + ethrx_dpio_dev = DPAA2_PER_LCORE_ETHRX_DPIO; + q_storage = &sch_dev->q_storage[rte_lcore_id()]; + + pull_size = (nb_pkts > dpaa2_dqrr_size) ? + dpaa2_dqrr_size : nb_pkts; + if (likely(q_storage->active_dqs)) + goto pull_active_dqs; + + q_storage->toggle = 0; + dq_storage = q_storage->dq_storage[q_storage->toggle]; + iova_storage = q_storage->iova_dq_storage[q_storage->toggle]; + q_storage->last_num_pkts = pull_size; + dpaa2_qbman_pull_desc_channel_set(&pulldesc, nb_pkts, + ch_id, dq_storage, iova_storage); + if (check_swp_active_dqs(ethrx_dpio_dev->index)) { + do { + active = get_swp_active_dqs(ethrx_dpio_dev->index); + if (qbman_check_command_complete(active)) + break; + } while (1); + clear_swp_active_dqs(ethrx_dpio_dev->index); + } + while (1) { + if (qbman_swp_pull(swp, &pulldesc)) { + DPAA2_EVENTDEV_DEBUG("Line(%d): QBMAN is busy", __LINE__); + /* Portal was busy, try again */ + continue; + } + break; + } + q_storage->active_dqs = dq_storage; + q_storage->active_dpio_id = ethrx_dpio_dev->index; + set_swp_active_dqs(ethrx_dpio_dev->index, dq_storage); + +pull_active_dqs: + + dq_storage = q_storage->active_dqs; + rte_prefetch0((void *)(size_t)(dq_storage)); + rte_prefetch0((void *)(size_t)(dq_storage + 1)); + + /* Prepare next pull descriptor. This will give space for the + * prefetching done on DQRR entries + */ + q_storage->toggle ^= 1; + dq_storage1 = q_storage->dq_storage[q_storage->toggle]; + iova_storage = q_storage->iova_dq_storage[q_storage->toggle]; + dpaa2_qbman_pull_desc_channel_set(&pulldesc, nb_pkts, + ch_id, dq_storage1, iova_storage); + + while (!qbman_check_command_complete(dq_storage)) + ; + active = get_swp_active_dqs(q_storage->active_dpio_id); + if (dq_storage == active) + clear_swp_active_dqs(q_storage->active_dpio_id); + + pending = 1; + + do { + /* Loop until the dq_storage is updated with + * new token by QBMAN + */ + while (!qbman_check_new_result(dq_storage)) + ; + rte_prefetch0((void *)((size_t)(dq_storage + 2))); + /* Check whether Last Pull command is Expired and + * setting Condition for Loop termination + */ + if (qbman_result_DQ_is_pull_complete(dq_storage)) { + pending = 0; + /* Check for valid frame. */ + status = qbman_result_DQ_flags(dq_storage); + if (unlikely(!(status & QBMAN_DQ_STAT_VALIDFRAME))) + continue; + } + + fd = qbman_result_DQ_fd(dq_storage); + rvq = (void *)qbman_result_DQ_fqd_ctx(dq_storage); + priv = rvq->eth_data->dev_private; + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + mbuf[rcvd_pkts] = dpaa2_eth_sg_fd_to_mbuf_export(priv, fd); + else + mbuf[rcvd_pkts] = dpaa2_eth_fd_to_mbuf_export(priv, fd); + dpaa2_dev_rx_mbuf_flc_offload_export(mbuf[rcvd_pkts], fd); + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf[rcvd_pkts]); + rcvd_pkts++; + + dq_storage++; + } while (pending); + + if (check_swp_active_dqs(ethrx_dpio_dev->index)) { + do { + active = get_swp_active_dqs(ethrx_dpio_dev->index); + if (qbman_check_command_complete(active)) + break; + } while (1); + clear_swp_active_dqs(ethrx_dpio_dev->index); + } + /* issue a volatile dequeue command for next pull */ + while (1) { + if (qbman_swp_pull(swp, &pulldesc)) { + DPAA2_EVENTDEV_DEBUG("Line(%d): QBMAN is busy", __LINE__); + continue; + } + break; + } + q_storage->active_dqs = dq_storage1; + q_storage->active_dpio_id = ethrx_dpio_dev->index; + set_swp_active_dqs(ethrx_dpio_dev->index, dq_storage1); + + return rcvd_pkts; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_init, 26.11) +void *rte_dpaa2_scheduler_init(void) +{ + struct dpaa2_dpcon_dev *dpcon_dev = NULL; + struct dpaa2_sch_dev *sch_dev = NULL; + char *env = getenv("DPAA2_SCHEDULE_RX_PREFETCH"); + int prefetch_enable = env ? atoi(env) : 1, ret, i; + + sch_dev = rte_zmalloc(NULL, sizeof(struct dpaa2_sch_dev), 0); + if (!sch_dev) { + DPAA2_EVENTDEV_ERR("Failed alloc scheduler device!!"); + goto err; + } + + ret = dpaa2_scheduler_dq_storage_init(sch_dev); + if (ret) + goto err; + + dpcon_dev = rte_dpaa2_alloc_dpcon_dev(); + if (!dpcon_dev) { + DPAA2_EVENTDEV_ERR("Failed alloc dpcon device!!"); + goto err; + } + sch_dev->dpcon_dev = dpcon_dev; + if (prefetch_enable) + sch_dev->rx_schedule = dpaa2_scheduler_prefetch_recv; + else + sch_dev->rx_schedule = dpaa2_scheduler_recv; + + return sch_dev; +err: + if (dpcon_dev) + rte_dpaa2_free_dpcon_dev(dpcon_dev); + if (sch_dev) { + for (i = 0; i < RTE_MAX_LCORE; i++) + dpaa2_free_dq_storage(&sch_dev->q_storage[i]); + rte_free(sch_dev); + } + + return NULL; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_start, 26.11) +int rte_dpaa2_scheduler_start(void *scheduler_handle) +{ + struct dpaa2_sch_dev *sch_dev = scheduler_handle; + int32_t ret = 0; + + if (sch_dev->dpcon_dev) { + ret = rte_dpaa2_dpcon_start(sch_dev->dpcon_dev); + if (ret) + DPAA2_EVENTDEV_ERR("Failed(%d) to start dpcon", ret); + } else { + DPAA2_EVENTDEV_ERR("No dpcon allocated"); + ret = -ENODEV; + } + + return ret; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_destroy, 26.11) +int rte_dpaa2_scheduler_destroy(void *scheduler_handle) +{ + struct dpaa2_sch_dev *sch_dev = scheduler_handle; + int32_t ret = 0; + + if (sch_dev->dpcon_dev) { + ret = rte_dpaa2_dpcon_stop(sch_dev->dpcon_dev); + if (ret) { + DPAA2_EVENTDEV_ERR("Failed(%d) to stop dpcon", ret); + /** Free anyway.*/ + } + rte_dpaa2_free_dpcon_dev(sch_dev->dpcon_dev); + } + + rte_free(sch_dev); + + return ret; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_add, 26.11) +int rte_dpaa2_scheduler_add(void *scheduler_handle, + uint16_t port_id, uint16_t rxq_id, uint8_t priority) +{ + struct dpaa2_sch_dev *sch_dev = scheduler_handle; + struct dpaa2_dpcon_dev *dpcon_dev; + struct rte_eth_dev *dev; + struct dpaa2_dev_priv *priv; + struct rte_event_eth_rx_adapter_queue_conf queue_conf; + int ret; + + if (!rte_pmd_dpaa2_dev_is_dpaa2(port_id)) + return -ENODEV; + + dev = &rte_eth_devices[port_id]; + priv = dev->data->dev_private; + if (rxq_id >= priv->nb_rx_queues) { + DPAA2_EVENTDEV_ERR("rxq_id(%d) >= queue number(%d)", + rxq_id, priv->nb_rx_queues); + return -EINVAL; + } + + if (sch_dev->port_queue_num >= DPAA2_SCH_PORT_QUEUE_MAX_NUM) { + DPAA2_EVENTDEV_ERR("Too many schedule queues"); + return -EINVAL; + } + + memset(&queue_conf, 0, sizeof(struct rte_event_eth_rx_adapter_queue_conf)); + dpcon_dev = sch_dev->dpcon_dev; + dpaa2_eth_eventq_prio_dpcon_to_ev(priority, dpcon_dev, &queue_conf); + queue_conf.ev.sched_type = RTE_SCHED_TYPE_PARALLEL; + ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon_dev, &queue_conf); + if (!ret) { + sch_dev->port_queue[sch_dev->port_queue_num].eth_dev = dev; + sch_dev->port_queue[sch_dev->port_queue_num].rxq_id = rxq_id; + sch_dev->port_queue[sch_dev->port_queue_num].priority = priority; + rte_memcpy(&sch_dev->port_queue[sch_dev->port_queue_num].queue_conf, + &queue_conf, sizeof(struct rte_event_eth_rx_adapter_queue_conf)); + sch_dev->port_queue[sch_dev->port_queue_num].configured = true; + sch_dev->port_queue_num++; + } + + return ret; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_rx, 26.11) +uint16_t +rte_dpaa2_scheduler_rx(void *scheduler_handle, struct rte_mbuf **mbuf, + uint16_t nb_pkts) +{ + struct dpaa2_sch_dev *sch_dev = scheduler_handle; + + return sch_dev->rx_schedule(sch_dev, mbuf, nb_pkts); +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_max_prio, 26.11) +uint16_t +rte_dpaa2_scheduler_max_prio(void *scheduler_handle) +{ + struct dpaa2_sch_dev *sch_dev = scheduler_handle; + + return sch_dev->dpcon_dev->num_priorities; +} diff --git a/drivers/event/dpaa2/meson.build b/drivers/event/dpaa2/meson.build index 62b8507652..d4aca38d02 100644 --- a/drivers/event/dpaa2/meson.build +++ b/drivers/event/dpaa2/meson.build @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright 2018 NXP +# Copyright 2018, 2026 NXP if not is_linux build = false @@ -9,6 +9,7 @@ deps += ['bus_vdev', 'net_dpaa2', 'crypto_dpaa2_sec'] sources = files( 'dpaa2_eventdev.c', 'dpaa2_eventdev_selftest.c', + 'dpaa2_scheduler.c' ) includes += include_directories('../../crypto/dpaa2_sec/') diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 552ac4c94d..849ab7049f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3332,14 +3332,12 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, else return -EINVAL; - priority = (RTE_EVENT_DEV_PRIORITY_LOWEST / queue_conf->ev.priority) * - (dpcon->num_priorities - 1); - if (!cfg) { DPAA2_PMD_ERR("%s: %s-rxq%d was not setup yet!", __func__, dev->data->name, eth_rx_queue_id); return -EINVAL; } + priority = dpaa2_eth_eventq_prio_ev_to_dpcon(dpcon, queue_conf); options = DPNI_QUEUE_OPT_DEST; cfg->destination.type = DPNI_DEST_DPCON; cfg->destination.id = dpcon->dpcon_id; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index d46fbd6d7d..e4b896f17c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -908,6 +908,33 @@ dpaa2_dpkg_insert_extract(struct dpkg_profile_cfg *kg_cfg, kg_cfg->num_extracts++; } +static inline void +dpaa2_eth_eventq_prio_dpcon_to_ev(uint8_t priority, + struct dpaa2_dpcon_dev *dpcon, + struct rte_event_eth_rx_adapter_queue_conf *queue_conf) +{ + uint8_t priority_step; + uint32_t priority_ev; + + priority_step = (RTE_EVENT_DEV_PRIORITY_LOWEST + 1 - + RTE_EVENT_DEV_PRIORITY_HIGHEST) / dpcon->num_priorities; + priority_ev = priority * priority_step; + if (priority_ev > RTE_EVENT_DEV_PRIORITY_LOWEST) + priority_ev = RTE_EVENT_DEV_PRIORITY_LOWEST; + queue_conf->ev.priority = priority_ev; +} + +static inline uint8_t +dpaa2_eth_eventq_prio_ev_to_dpcon(struct dpaa2_dpcon_dev *dpcon, + const struct rte_event_eth_rx_adapter_queue_conf *queue_conf) +{ + uint8_t priority_step; + + priority_step = (RTE_EVENT_DEV_PRIORITY_LOWEST + 1 - + RTE_EVENT_DEV_PRIORITY_HIGHEST) / dpcon->num_priorities; + return queue_conf->ev.priority / priority_step; +} + __rte_internal int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, int eth_rx_queue_id, @@ -971,5 +998,16 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +__rte_internal +struct rte_mbuf * +dpaa2_eth_fd_to_mbuf_export(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); +__rte_internal +struct rte_mbuf * +dpaa2_eth_sg_fd_to_mbuf_export(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd); +__rte_internal +void +dpaa2_dev_rx_mbuf_flc_offload_export(struct rte_mbuf *m, + const struct qbman_fd *fd); + int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); #endif /* _DPAA2_ETHDEV_H */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index d0d4536ab4..0d4fc18455 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -165,6 +165,13 @@ dpaa2_dev_rx_mbuf_flc_offload(struct rte_mbuf *m, } } +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_rx_mbuf_flc_offload_export) +void dpaa2_dev_rx_mbuf_flc_offload_export(struct rte_mbuf *m, + const struct qbman_fd *fd) +{ + dpaa2_dev_rx_mbuf_flc_offload(m, fd); +} + static inline void dpaa2_dev_rx_read_timestamp(struct dpaa2_dev_priv *priv, struct rte_mbuf *m) @@ -479,6 +486,13 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return (void *)first_seg; } +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_sg_fd_to_mbuf_export) +struct rte_mbuf * +dpaa2_eth_sg_fd_to_mbuf_export(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) +{ + return dpaa2_eth_sg_fd_to_mbuf(priv, fd); +} + static inline struct rte_mbuf *__rte_hot dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { @@ -534,6 +548,13 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) return mbuf; } +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_fd_to_mbuf_export) +struct rte_mbuf * +dpaa2_eth_fd_to_mbuf_export(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) +{ + return dpaa2_eth_fd_to_mbuf(priv, fd); +} + static void dpaa2_dev_tx_enable_tstamp(struct qbman_fd *fd) { struct dpaa2_faead *fd_faead; diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index b28962c5f8..eb038011c9 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -129,6 +129,34 @@ int rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off); +__rte_experimental +void * +rte_dpaa2_scheduler_init(void); +__rte_experimental +int +rte_dpaa2_scheduler_start(void *scheduler_handle); +__rte_experimental +int +rte_dpaa2_scheduler_destroy(void *scheduler_handle); +__rte_experimental +uint16_t +rte_dpaa2_scheduler_max_prio(void *scheduler_handle); +__rte_experimental +int +rte_dpaa2_scheduler_add(void *scheduler_handle, + uint16_t port_id, uint16_t rxq_id, uint8_t priority); + +/* rte_dpaa2_scheduler_rx()- DPCON scheduler receive function + * @scheduler_handle: DPCON scheduler handle + * @mbuf: Packet mbuf + * @nb_pkts: Number of packets to be received. + * Return Number of received packet. + */ +__rte_experimental +uint16_t +rte_dpaa2_scheduler_rx(void *scheduler_handle, struct rte_mbuf **mbuf, + uint16_t nb_pkts); + #define RTE_DPAA2_EVENT_PORT_CFG_ATOMIC RTE_BIT32(31) /** RTE_DPAA2_MIX_GROUP_FLOW has same behavio as RTE_DPAA2_FLAT_GROUP_FLOW*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 35/65] event/dpaa2: add push mode to DPCON Rx scheduler 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (33 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 34/65] event/dpaa2: add DPCON based standalone Rx scheduler Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 36/65] event/dpaa2: drain Rx scheduler queues on destroy Prashant Gupta ` (29 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Extend the DPCON standalone Rx scheduler with a second scheduling mode so callers can choose how packets reach the poll path. The mode is selected at init time through a new enum rte_dpaa2_sch_mode argument to rte_dpaa2_scheduler_init(): pull The original behaviour. A single shared DPCON channel is allocated and ethdev Rx queues are attached to it up front; packets are pulled from that channel via the plain or prefetch receive path. push A per-lcore DPCON plus DPCI pair is allocated lazily on first receive. The DPCI is linked to the DPCON, the pending Rx queues are attached, and the DPCON channel is added as a static dequeue channel so frames are pushed into the software portal DQRR and consumed in place (dpaa2_scheduler_dpci_recv). To support push mode, struct dpaa2_sch_dev now holds per-lcore dpcon and dpci arrays and a per-lcore linked flag instead of a single DPCON pointer. rte_dpaa2_scheduler_add() defers hardware attach for push mode (recording the queue and doing the attach on the first receive on each lcore), while pull mode still attaches immediately. start and destroy are updated to walk the per-lcore arrays: destroy stops linked DPCONs, frees both the DPCON and DPCI devices, and reports the first stop error while still freeing everything. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_scheduler.c | 189 ++++++++++++++++++++++---- drivers/net/dpaa2/rte_pmd_dpaa2.h | 7 +- 2 files changed, 167 insertions(+), 29 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c b/drivers/event/dpaa2/dpaa2_scheduler.c index e553c4d3f6..51956ac1e5 100644 --- a/drivers/event/dpaa2/dpaa2_scheduler.c +++ b/drivers/event/dpaa2/dpaa2_scheduler.c @@ -41,9 +41,12 @@ struct dpaa2_sch_port_queue { }; struct dpaa2_sch_dev { - struct dpaa2_dpcon_dev *dpcon_dev; + struct dpaa2_dpcon_dev *dpcon_dev[RTE_MAX_LCORE]; + struct dpaa2_dpci_dev *dpci_dev[RTE_MAX_LCORE]; + uint8_t linked[RTE_MAX_LCORE]; struct dpaa2_sch_port_queue port_queue[DPAA2_SCH_PORT_QUEUE_MAX_NUM]; uint8_t port_queue_num; + enum rte_dpaa2_sch_mode sch_mode; struct queue_storage_info_t q_storage[RTE_MAX_LCORE]; uint16_t (*rx_schedule)(struct dpaa2_sch_dev *dev, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); @@ -83,11 +86,110 @@ dpaa2_qbman_pull_desc_channel_set(struct qbman_pull_desc *pulldesc, iova_storage, 1); } +static uint16_t +dpaa2_scheduler_dpci_recv(struct dpaa2_sch_dev *sch_dev, + struct rte_mbuf **mbuf, uint16_t nb_pkts) +{ + const struct qbman_result *dq; + struct dpaa2_dpcon_dev *dpcon_dev; + struct dpaa2_dpci_dev *dpci_dev; + struct dpaa2_dpio_dev *dpio_dev; + struct qbman_swp *swp; + const struct qbman_fd *fd; + struct dpaa2_queue *rxq; + struct dpaa2_sch_port_queue *port_queue; + struct rte_event_eth_rx_adapter_queue_conf *queue_conf; + uint16_t num_pkts = 0, i = 0; + int ret; + struct dpaa2_dev_priv *priv; + uint32_t cpu = rte_lcore_id(); + + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); + if (ret) { + DPAA2_EVENTDEV_ERR("Failure(%d) in affining portal", ret); + return 0; + } + } + dpio_dev = DPAA2_PER_LCORE_ETHRX_DPIO; + swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + if (likely(sch_dev->linked[cpu] == sch_dev->port_queue_num)) + goto start_dq; + if (!sch_dev->dpcon_dev[cpu]) + sch_dev->dpcon_dev[cpu] = rte_dpaa2_alloc_dpcon_dev(); + if (!sch_dev->dpci_dev[cpu]) + sch_dev->dpci_dev[cpu] = rte_dpaa2_alloc_dpci_dev(); + if (!sch_dev->dpcon_dev[cpu] || !sch_dev->dpci_dev[cpu]) + return 0; + dpcon_dev = sch_dev->dpcon_dev[cpu]; + dpci_dev = sch_dev->dpci_dev[cpu]; + ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, + dpcon_dev->dpcon_id, 0, NULL, NULL); + if (ret) { + DPAA2_EVENTDEV_ERR("DPCI link attaches dpcon failed: err(%d)", ret); + return 0; + } + for (i = 0; i < sch_dev->port_queue_num; i++) { + port_queue = &sch_dev->port_queue[i]; + if (port_queue->configured) + continue; + queue_conf = &port_queue->queue_conf; + dpaa2_eth_eventq_prio_dpcon_to_ev(port_queue->priority, + dpcon_dev, queue_conf); + ret = dpaa2_eth_eventq_attach(port_queue->eth_dev, + port_queue->rxq_id, dpcon_dev, queue_conf); + if (ret) { + DPAA2_EVENTDEV_ERR("Failure(%d) attaching %s-rxq%d to eventq", + ret, port_queue->eth_dev->data->name, + port_queue->rxq_id); + return 0; + } + port_queue->configured = true; + } + ret = dpio_add_static_dequeue_channel(dpio_dev->dpio, + CMD_PRI_LOW, dpio_dev->token, + dpcon_dev->dpcon_id, + &dpcon_dev->channel_index); + if (ret) { + DPAA2_EVENTDEV_ERR("Failure(%d) adding dpcon%d to static dq channel", + ret, dpcon_dev->dpcon_id); + return 0; + } + + qbman_swp_push_set(swp, dpcon_dev->channel_index, 1); + sch_dev->linked[cpu] = sch_dev->port_queue_num; + +start_dq: + do { + dq = qbman_swp_dqrr_next(swp); + if (!dq) + goto quit; + + qbman_swp_prefetch_dqrr_next(swp); + + fd = qbman_result_DQ_fd(dq); + rxq = (void *)qbman_result_DQ_fqd_ctx(dq); + priv = rxq->eth_data->dev_private; + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + mbuf[num_pkts] = dpaa2_eth_sg_fd_to_mbuf_export(priv, fd); + else + mbuf[num_pkts] = dpaa2_eth_fd_to_mbuf_export(priv, fd); + dpaa2_dev_rx_mbuf_flc_offload_export(mbuf[num_pkts], fd); + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf[num_pkts]); + qbman_swp_dqrr_consume(swp, dq); + + num_pkts++; + } while (num_pkts < nb_pkts); + +quit: + return num_pkts; +} + static uint16_t dpaa2_scheduler_recv(struct dpaa2_sch_dev *sch_dev, struct rte_mbuf **mbuf, uint16_t nb_pkts) { - struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev; + struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev[0]; uint16_t ch_id = dpcon_dev->qbman_ch_id; struct qbman_result *dq_sch_storage; uint16_t total_nb_pkts = nb_pkts; @@ -179,7 +281,7 @@ static uint16_t dpaa2_scheduler_prefetch_recv(struct dpaa2_sch_dev *sch_dev, struct rte_mbuf **mbuf, uint16_t nb_pkts) { - struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev; + struct dpaa2_dpcon_dev *dpcon_dev = sch_dev->dpcon_dev[0]; uint16_t ch_id = dpcon_dev->qbman_ch_id, pull_size; struct qbman_result *dq_storage, *dq_storage1 = NULL, *active; struct qbman_pull_desc pulldesc; @@ -314,7 +416,7 @@ dpaa2_scheduler_prefetch_recv(struct dpaa2_sch_dev *sch_dev, } RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_init, 26.11) -void *rte_dpaa2_scheduler_init(void) +void *rte_dpaa2_scheduler_init(enum rte_dpaa2_sch_mode sch_mode) { struct dpaa2_dpcon_dev *dpcon_dev = NULL; struct dpaa2_sch_dev *sch_dev = NULL; @@ -331,16 +433,24 @@ void *rte_dpaa2_scheduler_init(void) if (ret) goto err; - dpcon_dev = rte_dpaa2_alloc_dpcon_dev(); - if (!dpcon_dev) { - DPAA2_EVENTDEV_ERR("Failed alloc dpcon device!!"); + if (sch_mode == RTE_DPAA2_SCH_PULL) { + dpcon_dev = rte_dpaa2_alloc_dpcon_dev(); + if (!dpcon_dev) { + DPAA2_EVENTDEV_ERR("Failed alloc dpcon device!!"); + goto err; + } + sch_dev->dpcon_dev[0] = dpcon_dev; + if (prefetch_enable) + sch_dev->rx_schedule = dpaa2_scheduler_prefetch_recv; + else + sch_dev->rx_schedule = dpaa2_scheduler_recv; + } else if (sch_mode == RTE_DPAA2_SCH_PUSH) { + sch_dev->rx_schedule = dpaa2_scheduler_dpci_recv; + } else { + DPAA2_EVENTDEV_ERR("Invalid schedule mode(%d)!!", sch_mode); goto err; } - sch_dev->dpcon_dev = dpcon_dev; - if (prefetch_enable) - sch_dev->rx_schedule = dpaa2_scheduler_prefetch_recv; - else - sch_dev->rx_schedule = dpaa2_scheduler_recv; + sch_dev->sch_mode = sch_mode; return sch_dev; err: @@ -361,15 +471,22 @@ int rte_dpaa2_scheduler_start(void *scheduler_handle) struct dpaa2_sch_dev *sch_dev = scheduler_handle; int32_t ret = 0; - if (sch_dev->dpcon_dev) { - ret = rte_dpaa2_dpcon_start(sch_dev->dpcon_dev); - if (ret) + if (sch_dev->sch_mode == RTE_DPAA2_SCH_PUSH) + goto start_quit; + + if (sch_dev->dpcon_dev[0]) { + ret = rte_dpaa2_dpcon_start(sch_dev->dpcon_dev[0]); + if (ret) { DPAA2_EVENTDEV_ERR("Failed(%d) to start dpcon", ret); + return ret; + } + sch_dev->linked[0] = 1; } else { DPAA2_EVENTDEV_ERR("No dpcon allocated"); ret = -ENODEV; } +start_quit: return ret; } @@ -377,15 +494,27 @@ RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_destroy, 26.11) int rte_dpaa2_scheduler_destroy(void *scheduler_handle) { struct dpaa2_sch_dev *sch_dev = scheduler_handle; - int32_t ret = 0; + struct dpaa2_dpcon_dev *dpcon_dev; + struct dpaa2_dpci_dev *dpci_dev; + int32_t ret = 0, _ret, i; - if (sch_dev->dpcon_dev) { - ret = rte_dpaa2_dpcon_stop(sch_dev->dpcon_dev); - if (ret) { - DPAA2_EVENTDEV_ERR("Failed(%d) to stop dpcon", ret); - /** Free anyway.*/ + for (i = 0; i < RTE_MAX_LCORE; i++) { + dpcon_dev = sch_dev->dpcon_dev[i]; + dpci_dev = sch_dev->dpci_dev[i]; + if (dpcon_dev) { + if (sch_dev->linked[i]) { + _ret = rte_dpaa2_dpcon_stop(dpcon_dev); + if (_ret) { + DPAA2_EVENTDEV_ERR("Failed(%d) to stop dpcon[%d]", _ret, i); + /** Free anyway.*/ + ret = _ret; + } + } + rte_dpaa2_free_dpcon_dev(dpcon_dev); } - rte_dpaa2_free_dpcon_dev(sch_dev->dpcon_dev); + if (dpci_dev) + rte_dpaa2_free_dpci_dev(dpci_dev); + sch_dev->linked[i] = 0; } rte_free(sch_dev); @@ -421,17 +550,21 @@ int rte_dpaa2_scheduler_add(void *scheduler_handle, } memset(&queue_conf, 0, sizeof(struct rte_event_eth_rx_adapter_queue_conf)); - dpcon_dev = sch_dev->dpcon_dev; - dpaa2_eth_eventq_prio_dpcon_to_ev(priority, dpcon_dev, &queue_conf); - queue_conf.ev.sched_type = RTE_SCHED_TYPE_PARALLEL; - ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon_dev, &queue_conf); + ret = 0; + if (sch_dev->sch_mode == RTE_DPAA2_SCH_PULL) { + dpcon_dev = sch_dev->dpcon_dev[0]; + dpaa2_eth_eventq_prio_dpcon_to_ev(priority, dpcon_dev, &queue_conf); + queue_conf.ev.sched_type = RTE_SCHED_TYPE_PARALLEL; + ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon_dev, &queue_conf); + } if (!ret) { sch_dev->port_queue[sch_dev->port_queue_num].eth_dev = dev; sch_dev->port_queue[sch_dev->port_queue_num].rxq_id = rxq_id; sch_dev->port_queue[sch_dev->port_queue_num].priority = priority; rte_memcpy(&sch_dev->port_queue[sch_dev->port_queue_num].queue_conf, &queue_conf, sizeof(struct rte_event_eth_rx_adapter_queue_conf)); - sch_dev->port_queue[sch_dev->port_queue_num].configured = true; + if (sch_dev->sch_mode == RTE_DPAA2_SCH_PULL) + sch_dev->port_queue[sch_dev->port_queue_num].configured = true; sch_dev->port_queue_num++; } @@ -454,5 +587,5 @@ rte_dpaa2_scheduler_max_prio(void *scheduler_handle) { struct dpaa2_sch_dev *sch_dev = scheduler_handle; - return sch_dev->dpcon_dev->num_priorities; + return sch_dev->dpcon_dev[0]->num_priorities; } diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index eb038011c9..5125ec5bf7 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -129,9 +129,14 @@ int rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, uint8_t *l3_off, uint8_t *l4_off, uint8_t *l5_off); +enum rte_dpaa2_sch_mode { + RTE_DPAA2_SCH_PULL, + RTE_DPAA2_SCH_PUSH +}; + __rte_experimental void * -rte_dpaa2_scheduler_init(void); +rte_dpaa2_scheduler_init(enum rte_dpaa2_sch_mode sch_mode); __rte_experimental int rte_dpaa2_scheduler_start(void *scheduler_handle); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 36/65] event/dpaa2: drain Rx scheduler queues on destroy 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (34 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 35/65] event/dpaa2: add push mode to DPCON " Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 37/65] event/dpaa2: track and detach attached Rx queues Prashant Gupta ` (28 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Refactor the per-DQRR-entry receive code into a shared helper (dpaa2_scheduler_swp_mbuf_dq) used by both the fast-path push receive and the new teardown drain, then drain any in-flight packets when the scheduler is destroyed so buffers are not leaked or left stuck in the hardware channel. For push mode, destroy now walks each lcore that has an active portal: it repeatedly dequeues and frees frames from the software portal (dpaa2_scheduler_dpio_drain), clears the push enable, and removes the DPCON static dequeue channel before the DPCON and DPCI devices are freed. A per-lcore dpio_dev array is added to struct dpaa2_sch_dev so destroy can find the portal that was bound on first receive. For pull mode, destroy repeatedly calls the configured receive path and frees the returned mbufs in bulk until the channel is empty (dpaa2_scheduler_rx_pull_drain). Any nonzero drained count is logged as a warning, and channel-removal errors are propagated as the destroy return value while teardown still completes. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_scheduler.c | 141 +++++++++++++++++++++----- 1 file changed, 117 insertions(+), 24 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c b/drivers/event/dpaa2/dpaa2_scheduler.c index 51956ac1e5..26e3f50cf7 100644 --- a/drivers/event/dpaa2/dpaa2_scheduler.c +++ b/drivers/event/dpaa2/dpaa2_scheduler.c @@ -43,6 +43,7 @@ struct dpaa2_sch_port_queue { struct dpaa2_sch_dev { struct dpaa2_dpcon_dev *dpcon_dev[RTE_MAX_LCORE]; struct dpaa2_dpci_dev *dpci_dev[RTE_MAX_LCORE]; + struct dpaa2_dpio_dev *dpio_dev[RTE_MAX_LCORE]; uint8_t linked[RTE_MAX_LCORE]; struct dpaa2_sch_port_queue port_queue[DPAA2_SCH_PORT_QUEUE_MAX_NUM]; uint8_t port_queue_num; @@ -86,22 +87,68 @@ dpaa2_qbman_pull_desc_channel_set(struct qbman_pull_desc *pulldesc, iova_storage, 1); } +static inline struct rte_mbuf * +dpaa2_scheduler_swp_mbuf_dq(struct qbman_swp *swp) +{ + const struct qbman_result *dq; + const struct qbman_fd *fd; + struct dpaa2_queue *rxq; + struct dpaa2_dev_priv *priv; + struct rte_mbuf *mbuf; + + dq = qbman_swp_dqrr_next(swp); + if (!dq) + return NULL; + + qbman_swp_prefetch_dqrr_next(swp); + fd = qbman_result_DQ_fd(dq); + rxq = (void *)qbman_result_DQ_fqd_ctx(dq); + priv = rxq->eth_data->dev_private; + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + mbuf = dpaa2_eth_sg_fd_to_mbuf_export(priv, fd); + else + mbuf = dpaa2_eth_fd_to_mbuf_export(priv, fd); + dpaa2_dev_rx_mbuf_flc_offload_export(mbuf, fd); + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); + qbman_swp_dqrr_consume(swp, dq); + + return mbuf; +} + +static uint32_t +dpaa2_scheduler_dpio_drain(struct dpaa2_dpio_dev *dpio_dev) +{ + struct qbman_swp *swp; + uint32_t num_pkts = 0; + int max_drain = 1000; + struct rte_mbuf *mbuf; + + swp = dpio_dev->sw_portal; + + while (max_drain--) { + mbuf = dpaa2_scheduler_swp_mbuf_dq(swp); + if (!mbuf) + break; + rte_pktmbuf_free(mbuf); + num_pkts++; + rte_delay_ms(1); + } + + return num_pkts; +} + static uint16_t dpaa2_scheduler_dpci_recv(struct dpaa2_sch_dev *sch_dev, struct rte_mbuf **mbuf, uint16_t nb_pkts) { - const struct qbman_result *dq; struct dpaa2_dpcon_dev *dpcon_dev; struct dpaa2_dpci_dev *dpci_dev; struct dpaa2_dpio_dev *dpio_dev; struct qbman_swp *swp; - const struct qbman_fd *fd; - struct dpaa2_queue *rxq; struct dpaa2_sch_port_queue *port_queue; struct rte_event_eth_rx_adapter_queue_conf *queue_conf; uint16_t num_pkts = 0, i = 0; int ret; - struct dpaa2_dev_priv *priv; uint32_t cpu = rte_lcore_id(); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -158,30 +205,17 @@ dpaa2_scheduler_dpci_recv(struct dpaa2_sch_dev *sch_dev, qbman_swp_push_set(swp, dpcon_dev->channel_index, 1); sch_dev->linked[cpu] = sch_dev->port_queue_num; + sch_dev->dpio_dev[cpu] = dpio_dev; start_dq: - do { - dq = qbman_swp_dqrr_next(swp); - if (!dq) - goto quit; - - qbman_swp_prefetch_dqrr_next(swp); - - fd = qbman_result_DQ_fd(dq); - rxq = (void *)qbman_result_DQ_fqd_ctx(dq); - priv = rxq->eth_data->dev_private; - if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - mbuf[num_pkts] = dpaa2_eth_sg_fd_to_mbuf_export(priv, fd); + while (num_pkts < nb_pkts) { + mbuf[num_pkts] = dpaa2_scheduler_swp_mbuf_dq(swp); + if (likely(mbuf[num_pkts])) + num_pkts++; else - mbuf[num_pkts] = dpaa2_eth_fd_to_mbuf_export(priv, fd); - dpaa2_dev_rx_mbuf_flc_offload_export(mbuf[num_pkts], fd); - dpaa2_dev_rx_print_parser_result(priv, fd, mbuf[num_pkts]); - qbman_swp_dqrr_consume(swp, dq); - - num_pkts++; - } while (num_pkts < nb_pkts); + break; + } -quit: return num_pkts; } @@ -490,6 +524,54 @@ int rte_dpaa2_scheduler_start(void *scheduler_handle) return ret; } +static int +dpaa2_scheduler_rx_core_push_drain(struct dpaa2_sch_dev *sch_dev, uint16_t core) +{ + struct dpaa2_dpio_dev *dpio_dev; + struct dpaa2_dpcon_dev *dpcon_dev; + uint16_t drain_num; + int ret; + + if (!sch_dev->dpio_dev[core]) + return 0; + + dpio_dev = sch_dev->dpio_dev[core]; + dpcon_dev = sch_dev->dpcon_dev[core]; + if (!dpcon_dev) + return -ENODEV; + drain_num = dpaa2_scheduler_dpio_drain(dpio_dev); + if (drain_num > 0) + DPAA2_EVENTDEV_WARN("Drain %d buffer(s) from core%d", drain_num, core); + + qbman_swp_push_set(dpio_dev->sw_portal, dpcon_dev->channel_index, 0); + ret = dpio_remove_static_dequeue_channel(dpio_dev->dpio, + 0, dpio_dev->token, dpcon_dev->dpcon_id); + if (ret) + DPAA2_EVENTDEV_ERR("Failed(%d) to remove channel on core%d", ret, core); + + return ret; +} + +static void +dpaa2_scheduler_rx_pull_drain(struct dpaa2_sch_dev *sch_dev) +{ + uint16_t drain_num = 0, rx; + struct rte_mbuf *mbufs[16]; + int max_drain = 1000; + +rx_again: + rx = sch_dev->rx_schedule(sch_dev, mbufs, 16); + rte_pktmbuf_free_bulk(mbufs, rx); + drain_num += rx; + if (rx > 0 && max_drain > 0) { + rte_delay_ms(1); + max_drain--; + goto rx_again; + } + if (drain_num > 0) + DPAA2_EVENTDEV_WARN("Drain %d buffer(s) from scheduler.", drain_num); +} + RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_scheduler_destroy, 26.11) int rte_dpaa2_scheduler_destroy(void *scheduler_handle) { @@ -498,6 +580,17 @@ int rte_dpaa2_scheduler_destroy(void *scheduler_handle) struct dpaa2_dpci_dev *dpci_dev; int32_t ret = 0, _ret, i; + if (sch_dev->sch_mode == RTE_DPAA2_SCH_PUSH) { + /** Make sure all data threads quit.*/ + for (i = 0; i < RTE_MAX_LCORE; i++) { + _ret = dpaa2_scheduler_rx_core_push_drain(sch_dev, i); + if (_ret) + ret = _ret; + } + } else { + dpaa2_scheduler_rx_pull_drain(sch_dev); + } + for (i = 0; i < RTE_MAX_LCORE; i++) { dpcon_dev = sch_dev->dpcon_dev[i]; dpci_dev = sch_dev->dpci_dev[i]; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 37/65] event/dpaa2: track and detach attached Rx queues 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (35 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 36/65] event/dpaa2: drain Rx scheduler queues on destroy Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 38/65] net/dpaa2: add multi-port Tx API Prashant Gupta ` (27 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 eventdev previously attached ethdev/crypto Rx queues to an event queue but never tracked or detached them, so device close and ethdev stop left the queues wired to a DPCON and leaked event state. Track each attached DPNI Rx queue in the owning event queue and add the plumbing to tear it down cleanly: - Record attached Rx queues: dpaa2_eventq now keeps an array of attached DPNI Rx queues (dpni_rxqs / dpni_rxq_num, capped at DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX) and dpaa2_queue gains an event_attached flag. The ethdev tracks the number of attached queues in evq_attach_num and warns on close if any remain. - Detach by Rx queue: add dpaa2_eth_eventq_detach_by_rxq(), which detaches a queue given its dpaa2_queue directly (looking up the DPNI from the queue's eth_data), and refuses queues that were never attached. dpaa2_eth_eventq_detach() now validates the queue id and delegates to it. rx_queue_release skips queues still attached to the event device. - Eventdev lifecycle: add a DPAA2_EVENTDEV_CREATED/STARTED/STOPPED status and implement eth_queue_del, eth_stop, and close so they drain traffic and detach all attached Rx queues. eth_stop drains ingress by cycling stop/start on a local copy of the device before detaching. - Error propagation: crypto_queue_add_all now returns the last attach error instead of discarding it, and crypto_queue_add reports the queue-pair index. - Scheduler teardown: rte_dpaa2_scheduler_destroy() now detaches the event queues it attached (tracked via attach_num) as part of destroy. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/event/dpaa2/dpaa2_eventdev.c | 308 ++++++++++++++++-------- drivers/event/dpaa2/dpaa2_eventdev.h | 11 +- drivers/event/dpaa2/dpaa2_scheduler.c | 28 ++- drivers/net/dpaa2/dpaa2_ethdev.c | 57 ++++- drivers/net/dpaa2/dpaa2_ethdev.h | 4 + 6 files changed, 293 insertions(+), 116 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index b00e52a9b7..a0b1d2abfa 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -192,6 +192,7 @@ struct __rte_cache_aligned dpaa2_queue { uint8_t options; struct rte_event ev; struct rte_mempool *env_pool; + uint8_t event_attached; dpaa2_queue_cb_dqrr_t *cb; dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free; struct dpaa2_bp_info *bp_array; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 78a069b456..476decbbdc 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -41,6 +41,32 @@ #include <portal/dpaa2_hw_pvt.h> #include <mc/fsl_dpci.h> +static int +dpaa2_eventdev_attach_eth_rxq(const struct rte_eth_dev *dev, + struct dpaa2_eventdev *priv, uint16_t rxq_id, + const struct rte_event_eth_rx_adapter_queue_conf *queue_conf) +{ + int ret; + uint8_t ev_qid = queue_conf->ev.queue_id; + uint8_t idx = priv->evq_info[ev_qid].dpni_rxq_num; + struct dpaa2_dpcon_dev *dpcon = priv->evq_info[ev_qid].dpcon; + + if (idx >= DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX) { + DPAA2_EVENTDEV_ERR("Too many queues to attach."); + return -ENOMEM; + } + ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon, queue_conf); + if (ret) { + DPAA2_EVENTDEV_ERR("Event queue attach failed: err(%d)", ret); + + return ret; + } + priv->evq_info[ev_qid].dpni_rxqs[idx] = dev->data->rx_queues[rxq_id]; + priv->evq_info[ev_qid].dpni_rxq_num++; + + return 0; +} + /* Clarifications * Evendev = SoC Instance * Eventport = DPIO Instance @@ -309,6 +335,45 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], return num_pkts; } +static void +dpaa2_eventdev_dequeue_drain(const struct rte_eventdev *dev) +{ + uint16_t num, i, max; + struct rte_event ev; + struct dpaa2_port *dpaa2_portal; + + for (i = 0; i < dev->data->nb_ports; i++) { + dpaa2_portal = dev->data->ports[i]; + if (!dpaa2_portal || !dpaa2_portal->num_linked_evq) + continue; + /* Workers must be quiesced before this function is called. + * Concurrent portal access from a worker lcore during drain is undefined. + * Mark the port as draining so the dequeue path skips the + * cross-lcore warning. Do not touch cpu_affine here: it is + * read on the data path and mutating it would be a data race. + */ + rte_atomic_store_explicit(&dpaa2_portal->flushing, 1, + rte_memory_order_relaxed); + max = 0; +dq_again: + rte_delay_us(100); + num = dpaa2_eventdev_dequeue_burst(dpaa2_portal, &ev, 1, 1); + max++; + if (num && dev->dev_ops->dev_stop_flush) { + dev->dev_ops->dev_stop_flush(dev->data->dev_id, + ev, dev->data->dev_stop_flush_arg); + } + if (!num || max > 10000) { + rte_atomic_store_explicit(&dpaa2_portal->flushing, 0, + rte_memory_order_relaxed); + if (max > 10000 && num) + DPAA2_EVENTDEV_WARN("Quit with pending buffers"); + continue; + } + goto dq_again; + } +} + static void dpaa2_eventdev_info_get(struct rte_eventdev *dev, struct rte_event_dev_info *dev_info) @@ -392,9 +457,11 @@ dpaa2_eventdev_configure(const struct rte_eventdev *dev) static int dpaa2_eventdev_start(struct rte_eventdev *dev) { + struct dpaa2_eventdev *priv = dev->data->dev_private; + EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); + priv->status = DPAA2_EVENTDEV_STARTED; return 0; } @@ -402,52 +469,120 @@ dpaa2_eventdev_start(struct rte_eventdev *dev) static void dpaa2_eventdev_stop(struct rte_eventdev *dev) { - uint16_t num, i, max; - struct rte_event ev; - struct dpaa2_port *dpaa2_portal; + struct dpaa2_eventdev *priv = dev->data->dev_private; EVENTDEV_INIT_FUNC_TRACE(); - for (i = 0; i < dev->data->nb_ports; i++) { - dpaa2_portal = dev->data->ports[i]; - if (!dpaa2_portal || !dpaa2_portal->num_linked_evq) - continue; - /* Workers must be quiesced before rte_event_dev_stop() is called. - * Concurrent portal access from a worker lcore during drain is undefined. - * Mark the port as draining so the dequeue path skips the - * cross-lcore warning. Do not touch cpu_affine here: it is - * read on the data path and mutating it would be a data race. - */ - rte_atomic_store_explicit(&dpaa2_portal->flushing, 1, - rte_memory_order_relaxed); - max = 0; -dq_again: - rte_delay_us(100); - num = dpaa2_eventdev_dequeue_burst(dpaa2_portal, &ev, 1, 1); - max++; - if (num && dev->dev_ops->dev_stop_flush) { - dev->dev_ops->dev_stop_flush(dev->data->dev_id, - ev, dev->data->dev_stop_flush_arg); + dpaa2_eventdev_dequeue_drain(dev); + + priv->status = DPAA2_EVENTDEV_STOPPED; +} + +static void +dpaa2_eventdev_port_release(void *port) +{ + struct dpaa2_port *portal = port; + uint8_t port_id; + struct rte_eventdev *eventdev; + int ret; + + EVENTDEV_INIT_FUNC_TRACE(); + + if (!portal) + return; + + port_id = portal->port_id; + eventdev = portal->eventdev; + + /* TODO: Cleanup is required when ports are in linked state. */ + if (portal->num_linked_evq && eventdev) { + ret = rte_event_port_unlink(eventdev->data->dev_id, port_id, NULL, 0); + if (ret < 0) { + DPAA2_EVENTDEV_ERR("Event port.%d unlink all failed(%d)", + portal->port_id, ret); } - if (!num || max > 10000) { - rte_atomic_store_explicit(&dpaa2_portal->flushing, 0, - rte_memory_order_relaxed); - if (max > 10000 && num) - DPAA2_EVENTDEV_WARN("Quit with pending buffers"); + } + + if (portal->dpio_dev) + rte_dpaa2_free_dpio_device(portal->dpio_dev); + + rte_free(portal); + if (eventdev) + eventdev->data->ports[port_id] = NULL; +} + +static int +dpaa2_eventdev_eth_queue_del(const struct rte_eventdev *dev, + const struct rte_eth_dev *eth_dev, int32_t rx_queue_id) +{ + struct dpaa2_eventdev *priv = dev->data->dev_private; + struct dpaa2_eventq *evq; + uint8_t i, j, k, found = false; + int ret; + + EVENTDEV_INIT_FUNC_TRACE(); + + if (!eth_dev || rx_queue_id < 0) { + for (i = 0; i < priv->max_event_queues; i++) { + if (!priv->evq_info[i].valid) + continue; + evq = &priv->evq_info[i]; + for (j = 0; j < evq->dpni_rxq_num; j++) { + ret = dpaa2_eth_eventq_detach_by_rxq(evq->dpni_rxqs[j]); + if (ret) + return ret; + } + evq->dpni_rxq_num = 0; + } + + return 0; + } + + for (i = 0; i < priv->max_event_queues; i++) { + if (!priv->evq_info[i].valid) continue; + evq = &priv->evq_info[i]; + for (j = 0; j < evq->dpni_rxq_num; j++) { + if (evq->dpni_rxqs[j] == eth_dev->data->rx_queues[rx_queue_id]) { + found = true; + for (k = j + 1; k < evq->dpni_rxq_num; k++) + evq->dpni_rxqs[k - 1] = evq->dpni_rxqs[k]; + evq->dpni_rxq_num--; + goto start_detach; + } } - goto dq_again; } + +start_detach: + if (found) + return dpaa2_eth_eventq_detach(eth_dev, rx_queue_id); + + return -ENODEV; } static int dpaa2_eventdev_close(struct rte_eventdev *dev) { + struct dpaa2_eventdev *priv = dev->data->dev_private; + int i, ret; + EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); + if (priv->status == DPAA2_EVENTDEV_CREATED) + return 0; + if (priv->status == DPAA2_EVENTDEV_STARTED) + dpaa2_eventdev_stop(dev); - return 0; + for (i = 0; i < dev->data->nb_ports; i++) { + if (dev->data->ports[i]) + dpaa2_eventdev_port_release(dev->data->ports[i]); + } + + ret = dpaa2_eventdev_eth_queue_del(dev, NULL, -1); + if (!ret) + priv->status = DPAA2_EVENTDEV_CREATED; + + return ret; } static void @@ -650,39 +785,6 @@ dpaa2_eventdev_port_link(struct rte_eventdev *dev, void *port, return ret; } -static void -dpaa2_eventdev_port_release(void *port) -{ - struct dpaa2_port *portal = port; - uint8_t port_id; - struct rte_eventdev *eventdev; - int ret; - - EVENTDEV_INIT_FUNC_TRACE(); - - if (!portal) - return; - - port_id = portal->port_id; - eventdev = portal->eventdev; - - /* TODO: Cleanup is required when ports are in linked state. */ - if (portal->num_linked_evq && eventdev) { - ret = rte_event_port_unlink(eventdev->data->dev_id, port_id, NULL, 0); - if (ret < 0) { - DPAA2_EVENTDEV_ERR("Event port.%d unlink all failed(%d)", - portal->port_id, ret); - } - } - - if (portal->dpio_dev) - rte_dpaa2_free_dpio_device(portal->dpio_dev); - - rte_free(portal); - if (eventdev) - eventdev->data->ports[port_id] = NULL; -} - static int dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, const struct rte_event_port_conf *port_conf) @@ -766,14 +868,12 @@ dpaa2_eventdev_eth_queue_add_all(const struct rte_eventdev *dev, const struct rte_event_eth_rx_adapter_queue_conf *queue_conf) { struct dpaa2_eventdev *priv = dev->data->dev_private; - uint8_t ev_qid = queue_conf->ev.queue_id; - struct dpaa2_dpcon_dev *dpcon = priv->evq_info[ev_qid].dpcon; - int i, ret; + int i, ret, ret1; EVENTDEV_INIT_FUNC_TRACE(); for (i = 0; i < eth_dev->data->nb_rx_queues; i++) { - ret = dpaa2_eth_eventq_attach(eth_dev, i, dpcon, queue_conf); + ret = dpaa2_eventdev_attach_eth_rxq(eth_dev, priv, i, queue_conf); if (ret) { DPAA2_EVENTDEV_ERR("Event queue attach failed: err(%d)", ret); goto fail; @@ -781,8 +881,11 @@ dpaa2_eventdev_eth_queue_add_all(const struct rte_eventdev *dev, } return 0; fail: - for (i = (i - 1); i >= 0 ; i--) - dpaa2_eth_eventq_detach(eth_dev, i); + for (i = (i - 1); i >= 0 ; i--) { + ret1 = dpaa2_eventdev_eth_queue_del(dev, eth_dev, i); + if (ret1) + DPAA2_EVENTDEV_ERR("Failed(%d) to del q.%d in rollback", ret1, i); + } return ret; } @@ -794,34 +897,13 @@ dpaa2_eventdev_eth_queue_add(const struct rte_eventdev *dev, const struct rte_event_eth_rx_adapter_queue_conf *queue_conf) { struct dpaa2_eventdev *priv = dev->data->dev_private; - uint8_t ev_qid = queue_conf->ev.queue_id; - struct dpaa2_dpcon_dev *dpcon = priv->evq_info[ev_qid].dpcon; - int ret; EVENTDEV_INIT_FUNC_TRACE(); if (rx_queue_id < 0) return dpaa2_eventdev_eth_queue_add_all(dev, eth_dev, queue_conf); - ret = dpaa2_eth_eventq_attach(eth_dev, rx_queue_id, dpcon, queue_conf); - if (ret) - DPAA2_EVENTDEV_ERR("Event queue attach failed: err(%d)", ret); - - return ret; -} - -static int -dpaa2_eventdev_eth_queue_del(const struct rte_eventdev *dev, - const struct rte_eth_dev *eth_dev, - int32_t rx_queue_id) -{ - EVENTDEV_INIT_FUNC_TRACE(); - - RTE_SET_USED(dev); - RTE_SET_USED(eth_dev); - RTE_SET_USED(rx_queue_id); - - return 0; + return dpaa2_eventdev_attach_eth_rxq(eth_dev, priv, rx_queue_id, queue_conf); } static int @@ -838,12 +920,36 @@ dpaa2_eventdev_eth_start(const struct rte_eventdev *dev, static int dpaa2_eventdev_eth_stop(const struct rte_eventdev *dev, - const struct rte_eth_dev *eth_dev) + const struct rte_eth_dev *eth_dev) { + struct dpaa2_eventdev *priv = dev->data->dev_private; + int i, j, k, ret; + struct dpaa2_eventq *evq; + EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); - RTE_SET_USED(eth_dev); + /** Drain ingress traffic.*/ + dpaa2_eventdev_dequeue_drain(dev); + + for (i = 0; i < priv->max_event_queues; i++) { + evq = &priv->evq_info[i]; + if (!evq->valid) + continue; +search_again: + for (j = 0; j < evq->dpni_rxq_num; j++) { + if (evq->dpni_rxqs[j]->eth_data == eth_dev->data) { + ret = dpaa2_eth_eventq_detach_by_rxq(evq->dpni_rxqs[j]); + if (ret) { + DPAA2_EVENTDEV_ERR("detach rxq failed(%d)", ret); + return ret; + } + for (k = j + 1; k < evq->dpni_rxq_num; k++) + evq->dpni_rxqs[k - 1] = evq->dpni_rxqs[k]; + evq->dpni_rxq_num--; + goto search_again; + } + } + } return 0; } @@ -875,7 +981,7 @@ dpaa2_eventdev_crypto_queue_add_all(const struct rte_eventdev *dev, struct dpaa2_eventdev *priv = dev->data->dev_private; uint8_t ev_qid = ev->queue_id; struct dpaa2_dpcon_dev *dpcon = priv->evq_info[ev_qid].dpcon; - int i, ret; + int i, ret, ret1; EVENTDEV_INIT_FUNC_TRACE(); @@ -888,8 +994,11 @@ dpaa2_eventdev_crypto_queue_add_all(const struct rte_eventdev *dev, } return 0; fail: - for (i = (i - 1); i >= 0 ; i--) - dpaa2_sec_eventq_detach(cryptodev, i); + for (i = (i - 1); i >= 0 ; i--) { + ret1 = dpaa2_sec_eventq_detach(cryptodev, i); + if (ret1) + DPAA2_EVENTDEV_ERR("Failed(%d) to detach qp.%d in rollback", ret1, i); + } return ret; } @@ -1162,7 +1271,6 @@ dpaa2_eventdev_destroy(const char *name) if (priv->evq_info[i].dpci) rte_dpaa2_free_dpci_dev(priv->evq_info[i].dpci); - } priv->max_event_queues = 0; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index b6f23ec2e2..0a98088fe1 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -52,6 +52,7 @@ enum { */ #define DPAA2_EVENTQ_LINK_CONF_MAX 4 /** Max schedule type + 1.*/ +#define DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX 128 struct dpaa2_eventq { int valid; void *event_port; @@ -63,6 +64,8 @@ struct dpaa2_eventq { uint32_t event_queue_cfg; uint32_t event_queue_id; struct dpaa2_queue *dpci_txqs[DPAA2_EVENTQ_LINK_CONF_MAX]; + uint8_t dpni_rxq_num; + struct dpaa2_queue *dpni_rxqs[DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX]; }; struct dpaa2_port { @@ -83,13 +86,19 @@ struct dpaa2_port { uint64_t timeout_us; }; +enum dpaa2_eventdev_status { + DPAA2_EVENTDEV_CREATED, + DPAA2_EVENTDEV_STARTED, + DPAA2_EVENTDEV_STOPPED +}; + struct dpaa2_eventdev { struct dpaa2_eventq evq_info[DPAA2_EVENT_MAX_QUEUES]; uint32_t dequeue_timeout_ns; uint8_t max_event_queues; uint8_t nb_event_queues; uint8_t nb_event_ports; - uint8_t resvd_1; + uint8_t status; uint32_t nb_event_queue_flows; uint32_t nb_event_port_dequeue_depth; uint32_t nb_event_port_enqueue_depth; diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c b/drivers/event/dpaa2/dpaa2_scheduler.c index 26e3f50cf7..6a4ec04aae 100644 --- a/drivers/event/dpaa2/dpaa2_scheduler.c +++ b/drivers/event/dpaa2/dpaa2_scheduler.c @@ -524,8 +524,27 @@ int rte_dpaa2_scheduler_start(void *scheduler_handle) return ret; } +static void +dpaa2_scheduler_eventq_detach(struct dpaa2_sch_dev *sch_dev, + uint16_t un_attach_num) +{ + uint16_t i; + int ret; + + for (i = 0; i < un_attach_num; i++) { + ret = dpaa2_eth_eventq_detach(sch_dev->port_queue[i].eth_dev, + sch_dev->port_queue[i].rxq_id); + if (ret) { + DPAA2_EVENTDEV_ERR("Failed(%d) to detach %s's rxq%d", + ret, sch_dev->port_queue[i].eth_dev->data->name, + sch_dev->port_queue[i].rxq_id); + } + } +} + static int -dpaa2_scheduler_rx_core_push_drain(struct dpaa2_sch_dev *sch_dev, uint16_t core) +dpaa2_scheduler_rx_core_push_drain(struct dpaa2_sch_dev *sch_dev, + uint16_t core, uint16_t *attach_num) { struct dpaa2_dpio_dev *dpio_dev; struct dpaa2_dpcon_dev *dpcon_dev; @@ -544,6 +563,8 @@ dpaa2_scheduler_rx_core_push_drain(struct dpaa2_sch_dev *sch_dev, uint16_t core) DPAA2_EVENTDEV_WARN("Drain %d buffer(s) from core%d", drain_num, core); qbman_swp_push_set(dpio_dev->sw_portal, dpcon_dev->channel_index, 0); + if (attach_num) + (*attach_num)++; ret = dpio_remove_static_dequeue_channel(dpio_dev->dpio, 0, dpio_dev->token, dpcon_dev->dpcon_id); if (ret) @@ -579,17 +600,20 @@ int rte_dpaa2_scheduler_destroy(void *scheduler_handle) struct dpaa2_dpcon_dev *dpcon_dev; struct dpaa2_dpci_dev *dpci_dev; int32_t ret = 0, _ret, i; + uint16_t attach_num = 0; if (sch_dev->sch_mode == RTE_DPAA2_SCH_PUSH) { /** Make sure all data threads quit.*/ for (i = 0; i < RTE_MAX_LCORE; i++) { - _ret = dpaa2_scheduler_rx_core_push_drain(sch_dev, i); + _ret = dpaa2_scheduler_rx_core_push_drain(sch_dev, i, &attach_num); if (_ret) ret = _ret; } } else { dpaa2_scheduler_rx_pull_drain(sch_dev); + attach_num = sch_dev->port_queue_num; } + dpaa2_scheduler_eventq_detach(sch_dev, attach_num); for (i = 0; i < RTE_MAX_LCORE; i++) { dpcon_dev = sch_dev->dpcon_dev[i]; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 849ab7049f..c1a0ae7763 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1182,10 +1182,8 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) rte_atomic_store_explicit(&dpaa2_q->napi_sub_dpio, NULL, rte_memory_order_release); } - dpaa2_clear_queue_active_dps(dpaa2_q, - RTE_MAX_LCORE); - dpaa2_queue_storage_free(dpaa2_q, - RTE_MAX_LCORE); + dpaa2_clear_queue_active_dps(dpaa2_q, RTE_MAX_LCORE); + dpaa2_queue_storage_free(dpaa2_q, RTE_MAX_LCORE); if (dpaa2_q->cfg) rte_free(dpaa2_q->cfg); dpaa2_q->cfg = NULL; @@ -1557,6 +1555,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, qopt |= DPNI_QUEUE_OPT_USER_CTX; cfg->user_context = (size_t)(dpaa2_q); + cfg->destination.type = DPNI_DEST_NONE; /* napi: schedule the FQ to its DPCON once, when the channel is first * grabbed; never re-bound (the MC refuses scheduled->parked at runtime) @@ -1834,6 +1833,9 @@ dpaa2_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t rx_queue_id) PMD_INIT_FUNC_TRACE(); + if (dpaa2_q->event_attached) + return; + total_nb_rx_desc -= dpaa2_q->nb_desc; if (cfg) { @@ -2363,6 +2365,11 @@ dpaa2_dev_close(struct rte_eth_dev *dev) return -EINVAL; } + if (priv->evq_attach_num) { + DPAA2_PMD_WARN("%s's %d rxq(s) are not detached from event device..", + dev->data->name, priv->evq_attach_num); + } + dpaa2_tm_deinit(dev); dpaa2_flow_clean(dev, MAX_TCS, DPAA2_FLOW_ALL_TYPE); /** No matter dcb flows are created or not, they are destroyed in flow clean.*/ @@ -3400,29 +3407,53 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, dpaa2_ethq->ev.op = RTE_EVENT_OP_NEW; dpaa2_ethq->ev.queue_id = eth_rx_queue_id; + dpaa2_ethq->event_attached = true; + eth_priv->evq_attach_num++; + return 0; } -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_eventq_detach) -int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, - int eth_rx_queue_id) +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_eventq_detach_by_rxq) +int dpaa2_eth_eventq_detach_by_rxq(struct dpaa2_queue *dpaa2_ethq) { - struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; - struct fsl_mc_io *dpni = (struct fsl_mc_io *)dev->process_private; - struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; + struct dpaa2_dev_priv *eth_priv = dpaa2_ethq->eth_data->dev_private; + struct fsl_mc_io *dpni = eth_priv->hw; struct dpni_queue *cfg; int ret; + if (!dpaa2_ethq->event_attached) { + DPAA2_PMD_ERR("%s-tc%d-flow%d is not attached to event device.", + dpaa2_ethq->eth_data->name, dpaa2_ethq->tc_index, + dpaa2_ethq->flow_id); + + return -EINVAL; + } cfg = dpaa2_ethq->cfg; cfg->destination.type = DPNI_DEST_NONE; dpaa2_ethq->options &= ~DPNI_QUEUE_OPT_DEST; ret = dpni_set_queue(dpni, CMD_PRI_LOW, eth_priv->token, DPNI_QUEUE_RX, dpaa2_ethq->tc_index, dpaa2_ethq->flow_id, dpaa2_ethq->options, cfg); - if (ret) - DPAA2_PMD_ERR("Error in dpni_set_queue: ret: %d", ret); + if (ret) { + DPAA2_PMD_ERR("%s: failed(%d) to set rxq", __func__, ret); + return ret; + } - return ret; + dpaa2_ethq->event_attached = false; + eth_priv->evq_attach_num--; + + return 0; +} + +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_eth_eventq_detach) +int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, int queue_id) +{ + struct dpaa2_dev_priv *eth_priv = dev->data->dev_private; + + if (queue_id >= eth_priv->nb_rx_queues || queue_id < 0) + return -EINVAL; + + return dpaa2_eth_eventq_detach_by_rxq(eth_priv->rx_vq[queue_id]); } static int diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e4b896f17c..8c0be81c95 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -426,6 +426,7 @@ struct dpaa2_dev_priv { uint8_t cgid_in_use[MAX_TCS]; rte_spinlock_t meter_lock; + uint16_t evq_attach_num; uint16_t dpni_ver_major; uint16_t dpni_ver_minor; @@ -945,6 +946,9 @@ __rte_internal int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, int eth_rx_queue_id); +__rte_internal +int dpaa2_eth_eventq_detach_by_rxq(struct dpaa2_queue *dpaa2_ethq); + uint16_t dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); uint16_t dpaa2_dev_loopback_rx(void *queue, struct rte_mbuf **bufs, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 38/65] net/dpaa2: add multi-port Tx API 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (36 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 37/65] event/dpaa2: track and detach attached Rx queues Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 39/65] event/dpaa2: limit attached Rx flows per event queue Prashant Gupta ` (26 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add a public API to transmit an array of packets whose destination port and Tx queue are given per packet, and clean up the ordered Tx helpers it builds on. - New API rte_dpaa2_dev_tx_multi_ports(): takes per-packet port_id[] and txq_id[] arrays (txq_id NULL means queue 0 of each port), resolves each dpaa2_queue, and forwards to dpaa2_dev_tx_multi_txq_ordered(). This allows a single burst to span multiple ports. - dpaa2_dev_tx_multi_txq_ordered() takes struct dpaa2_queue ** instead of void ** and no longer loops with tx_again or accumulates a running "sent" count; it enqueues one batch and returns the number sent. Tx confirmation is now done after enqueue only for queues that have a tx_conf_queue, and the buffer-pool lookup is deferred to the slow path. - The dy_conf out-parameter is dropped from the mbuf-to-fd helpers (dpaa2_dev_tx_mbuf_to_sg_fd, dpaa2_dev_tx_mbuf_to_simple_fd, dpaa2_dev_tx_fast_mbuf_to_fd); it was written but never consumed. dpaa2_dev_tx_fast_mbuf_to_fd() now takes the private structure directly and reads tx_conf_type from it. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 2 +- drivers/net/dpaa2/dpaa2_ethdev.h | 4 +- drivers/net/dpaa2/dpaa2_rxtx.c | 127 ++++++++++++--------------- drivers/net/dpaa2/rte_pmd_dpaa2.h | 5 ++ 4 files changed, 66 insertions(+), 72 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 476decbbdc..be6d8bc3da 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -1095,7 +1095,7 @@ static uint16_t dpaa2_eventdev_txa_enqueue(void *port, struct rte_event ev[], uint16_t nb_events) { - void *txq[MAX_TX_RING_SLOTS]; + struct dpaa2_queue *txq[MAX_TX_RING_SLOTS]; struct rte_mbuf *m[MAX_TX_RING_SLOTS]; uint16_t sent = 0, burst, i, port_id, qid; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 8c0be81c95..e4dc7b7e4f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -975,8 +975,8 @@ uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); uint16_t dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); __rte_internal -uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, - struct rte_mbuf **bufs, uint16_t nb_pkts); +uint16_t dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, + struct rte_mbuf **bufs, uint16_t nb_pkts); void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id, diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 0d4fc18455..a44b991d1b 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -738,8 +738,7 @@ dpaa2_dev_tx_conf_mbuf_to_sge(struct qbman_sge *sgt, static int __rte_noinline __rte_hot dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, struct rte_mbuf *mbuf, struct qbman_fd *fd, - struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, - uint8_t *dy_conf, int tstamp) + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, int tstamp) { struct rte_mbuf *cur_seg = mbuf, *sg_mbuf; struct qbman_sge *sgt; @@ -841,8 +840,6 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, if (ret) return ret; } - if (dy_conf && need_dyconf) - *dy_conf = true; return 0; } @@ -867,8 +864,7 @@ dpaa2_dev_prefetch_next_psr(const struct qbman_result *dq) static int __rte_noinline __rte_hot dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, struct rte_mbuf *mbuf, struct qbman_fd *fd, - struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, - uint8_t *dy_conf, int tstamp) + struct dpaa2_queue *txq, enum dpaa2_tx_conf_type conf, int tstamp) { int need_dyconf = false, need_conf = false; struct rte_mbuf *mi; @@ -905,13 +901,10 @@ dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, rte_pktmbuf_free(mbuf); } - if (need_dyconf) { + if (need_dyconf) dpaa2_dev_tx_config_dynamic_confirm(fd, txq, true, tstamp); - if (dy_conf) - *dy_conf = true; - } else if (tstamp) { + else if (tstamp) dpaa2_dev_tx_enable_tstamp(fd); - } return ret; } @@ -1613,12 +1606,10 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) } static inline int -dpaa2_dev_tx_fast_mbuf_to_fd(struct rte_eth_dev_data *dev, - struct rte_mbuf *buf, struct qbman_fd *fd, - enum dpaa2_tx_conf_type conf) +dpaa2_dev_tx_fast_mbuf_to_fd(struct dpaa2_dev_priv *priv, + struct rte_mbuf *buf, struct qbman_fd *fd) { struct rte_mempool *mp = buf->pool; - struct dpaa2_dev_priv *priv = dev->dev_private; if (likely(RTE_MBUF_DIRECT(buf) && mp && mp->ops_index == @@ -1629,7 +1620,7 @@ dpaa2_dev_tx_fast_mbuf_to_fd(struct rte_eth_dev_data *dev, DPAA2_PMD_WARN("Single mbuf has next segment(%p)", buf->next); } - if (unlikely(conf == DPAA2_TX_ABSOLUTE_CONF)) + if (unlikely(priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF)) dpaa2_mbuf_to_conf_contig_fd(buf, fd); else DPAA2_MBUF_TO_CONTIG_FD(buf, fd, mempool_to_bpid(mp)); @@ -1662,7 +1653,6 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) struct dpaa2_dev_priv *priv = eth_data->dev_private; struct rte_mempool *hw_mp; uint32_t flags[MAX_TX_RING_SLOTS] = {0}; - uint8_t dy_conf[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -1709,7 +1699,6 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - dy_conf[loop] = false; if (*dpaa2_seqn(*bufs)) { uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; @@ -1739,8 +1728,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) goto skip_fast_mbuf2fd; } - ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, - *bufs, &fd_arr[loop], priv->tx_conf_type); + ret = dpaa2_dev_tx_fast_mbuf_to_fd(priv, *bufs, &fd_arr[loop]); if (likely(!ret)) { bufs++; continue; @@ -1749,10 +1737,10 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) skip_fast_mbuf2fd: if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); + dpaa2_q, priv->tx_conf_type, tstamp[loop]); } else { ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q, priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); + dpaa2_q, priv->tx_conf_type, tstamp[loop]); } if (ret) goto send_n_return; @@ -1849,11 +1837,9 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, static void dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, - struct rte_mbuf *m, - struct qbman_eq_desc *eqdesc) + struct rte_mbuf *m, struct qbman_eq_desc *eqdesc) { - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; struct eqresp_metadata *eqresp_meta; uint16_t orpid, seqnum; @@ -1896,22 +1882,20 @@ dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_tx_multi_txq_ordered) uint16_t -dpaa2_dev_tx_multi_txq_ordered(void **queue, +dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to multiple queues respectively.*/ - uint32_t loop, retry_count, sent = 0, i; + uint32_t loop, retry_count, i; int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; struct rte_mempool *hw_mp; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; - struct dpaa2_queue *dpaa2_q[MAX_TX_RING_SLOTS]; struct qbman_swp *swp; - struct rte_eth_dev_data *eth_data; struct dpaa2_dev_priv *priv; struct dpaa2_queue *order_sendq; - uint8_t dy_conf[MAX_TX_RING_SLOTS]; + struct dpaa2_queue *cnf_q; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -1923,25 +1907,12 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, } swp = DPAA2_PER_LCORE_PORTAL; -tx_again: ptp_set_count = 0; frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - dpaa2_q[loop] = queue[loop]; - if (dpaa2_q[loop]->tx_conf_queue) - dpaa2_dev_tx_conf(dpaa2_q[loop], false); - eth_data = dpaa2_q[loop]->eth_data; - priv = eth_data->dev_private; - dy_conf[loop] = false; - if (unlikely(!priv->bp_list)) { - DPAA2_PMD_ERR("%s's buffer pool not initialized!", - eth_data->name); - ret = -ENOMEM; - goto send_frames; - } - hw_mp = priv->bp_list->mp; + priv = dpaa2_q[loop]->eth_data->dev_private; if (!priv->en_loose_ordered && (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP)) { if (!num_free_eq_desc) { @@ -1954,9 +1925,6 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, num_free_eq_desc--; } - DPAA2_PMD_DP_DEBUG("===> eth_data =%p, fqid =%d", - eth_data, dpaa2_q[loop]->fqid); - /* Check if the queue is congested */ retry_count = 0; while (qbman_result_SCN_state(dpaa2_q[loop]->cscn)) { @@ -1973,8 +1941,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, if (*dpaa2_seqn(*bufs) && priv->en_ordered) { order_sendq = priv->tx_vq[0]; - dpaa2_set_enqueue_descriptor(order_sendq, *bufs, - &eqdesc[loop]); + dpaa2_set_enqueue_descriptor(order_sendq, *bufs, &eqdesc[loop]); } else { qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); @@ -1993,27 +1960,27 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, goto skip_fast_mbuf2fd; } - ret = dpaa2_dev_tx_fast_mbuf_to_fd(eth_data, - *bufs, &fd_arr[loop], priv->tx_conf_type); + ret = dpaa2_dev_tx_fast_mbuf_to_fd(priv, *bufs, &fd_arr[loop]); if (likely(!ret)) { - if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) - dy_conf[loop] = true; bufs++; continue; } skip_fast_mbuf2fd: + if (unlikely(!priv->bp_list)) { + ret = -ENOMEM; + goto send_frames; + } + hw_mp = priv->bp_list->mp; if (unlikely((*bufs)->nb_segs > 1)) { ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); + dpaa2_q[loop], priv->tx_conf_type, tstamp[loop]); } else { ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], - dpaa2_q[loop], priv->tx_conf_type, &dy_conf[loop], tstamp[loop]); + dpaa2_q[loop], priv->tx_conf_type, tstamp[loop]); } if (ret) goto send_frames; - if (priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF) - dy_conf[loop] = true; bufs++; } @@ -2023,8 +1990,7 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, retry_count = 0; while (loop < frames_to_send) { ret = qbman_swp_enqueue_multiple_desc(swp, &eqdesc[loop], - &fd_arr[loop], - frames_to_send - loop); + &fd_arr[loop], frames_to_send - loop); if (likely(ret > 0)) { loop += ret; retry_count = 0; @@ -2034,18 +2000,41 @@ dpaa2_dev_tx_multi_txq_ordered(void **queue, break; } } - nb_pkts -= loop; - sent += loop; for (i = 0; i < loop; i++) { - if (tstamp[i] && dpaa2_q[i]->tx_conf_queue) { - rte_atomic_fetch_add_explicit(&dpaa2_q[i]->tx_conf_queue->ts_to_cnfd, - 1, rte_memory_order_relaxed); + if (unlikely(dpaa2_q[i]->tx_conf_queue)) { + dpaa2_dev_tx_conf(dpaa2_q[i], false); + if (tstamp[i]) { + cnf_q = dpaa2_q[i]->tx_conf_queue; + rte_atomic_fetch_add_explicit(&cnf_q->ts_to_cnfd, + 1, rte_memory_order_relaxed); + } } } - if (nb_pkts > 0 && !ret) - goto tx_again; - return sent; + return loop; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_dpaa2_dev_tx_multi_ports, 26.11) +uint16_t +rte_dpaa2_dev_tx_multi_ports(uint16_t port_id[], + uint16_t txq_id[], struct rte_mbuf **bufs, uint16_t nb_pkts) +{ + uint16_t i; + struct dpaa2_queue *txq[nb_pkts]; + struct rte_eth_dev_data *data; + + if (txq_id) { + for (i = 0; i < nb_pkts; i++) { + data = rte_eth_devices[port_id[i]].data; + txq[i] = data->tx_queues[txq_id[i]]; + } + } else { + for (i = 0; i < nb_pkts; i++) { + data = rte_eth_devices[port_id[i]].data; + txq[i] = data->tx_queues[0]; + } + } + return dpaa2_dev_tx_multi_txq_ordered(txq, bufs, nb_pkts); } /* Callback to handle sending ordered packets through WRIOP based interface */ @@ -2054,7 +2043,7 @@ dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { uint16_t i; - void *mq[nb_pkts]; + struct dpaa2_queue *mq[nb_pkts]; for (i = 0; i < nb_pkts; i++) mq[i] = queue; diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index 5125ec5bf7..74b7e63c54 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -162,6 +162,11 @@ uint16_t rte_dpaa2_scheduler_rx(void *scheduler_handle, struct rte_mbuf **mbuf, uint16_t nb_pkts); +__rte_experimental +uint16_t +rte_dpaa2_dev_tx_multi_ports(uint16_t port_id[], + uint16_t txq_id[], struct rte_mbuf **bufs, uint16_t nb_pkts); + #define RTE_DPAA2_EVENT_PORT_CFG_ATOMIC RTE_BIT32(31) /** RTE_DPAA2_MIX_GROUP_FLOW has same behavio as RTE_DPAA2_FLAT_GROUP_FLOW*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 39/65] event/dpaa2: limit attached Rx flows per event queue 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (37 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 38/65] net/dpaa2: add multi-port Tx API Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 40/65] eventdev: fix port link/unlink callback return documentation Prashant Gupta ` (25 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The array tracking Rx queues attached to an event queue used a separate DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX (128) bound, which was unrelated to the event queue flow limit. Reuse the existing DPAA2_EVENT_MAX_QUEUE_FLOWS limit instead so a single value governs how many flows can target one event queue. Reduce DPAA2_EVENT_MAX_QUEUE_FLOWS from 2048 to 1024, size the dpni_rxqs[] array by that limit, and drop the now unused DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX define. Widen dpni_rxq_num and the local attach index to uint16_t so they can hold the larger count, and update the attach error message to report the offending event queue. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 6 +++--- drivers/event/dpaa2/dpaa2_eventdev.h | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index be6d8bc3da..cd2b00c3c9 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -48,11 +48,11 @@ dpaa2_eventdev_attach_eth_rxq(const struct rte_eth_dev *dev, { int ret; uint8_t ev_qid = queue_conf->ev.queue_id; - uint8_t idx = priv->evq_info[ev_qid].dpni_rxq_num; + uint16_t idx = priv->evq_info[ev_qid].dpni_rxq_num; struct dpaa2_dpcon_dev *dpcon = priv->evq_info[ev_qid].dpcon; - if (idx >= DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX) { - DPAA2_EVENTDEV_ERR("Too many queues to attach."); + if (idx >= DPAA2_EVENT_MAX_QUEUE_FLOWS) { + DPAA2_EVENTDEV_ERR("Too many flows to attach eventq%d", ev_qid); return -ENOMEM; } ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon, queue_conf); diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index 0a98088fe1..adeb22bda6 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -19,7 +19,7 @@ #define DPAA2_EVENT_MIN_DEQUEUE_TIMEOUT 1 #define DPAA2_EVENT_MAX_DEQUEUE_TIMEOUT (UINT32_MAX - 1) #define DPAA2_EVENT_PORT_DEQUEUE_TIMEOUT_NS 100UL -#define DPAA2_EVENT_MAX_QUEUE_FLOWS 2048 +#define DPAA2_EVENT_MAX_QUEUE_FLOWS 1024 #define DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS 8 #define DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS 0 #define DPAA2_EVENT_MAX_NUM_EVENTS (INT32_MAX - 1) @@ -52,7 +52,6 @@ enum { */ #define DPAA2_EVENTQ_LINK_CONF_MAX 4 /** Max schedule type + 1.*/ -#define DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX 128 struct dpaa2_eventq { int valid; void *event_port; @@ -64,8 +63,8 @@ struct dpaa2_eventq { uint32_t event_queue_cfg; uint32_t event_queue_id; struct dpaa2_queue *dpci_txqs[DPAA2_EVENTQ_LINK_CONF_MAX]; - uint8_t dpni_rxq_num; - struct dpaa2_queue *dpni_rxqs[DPAA2_EVENTQ_DPNI_RXQ_ATTACH_MAX]; + uint16_t dpni_rxq_num; + struct dpaa2_queue *dpni_rxqs[DPAA2_EVENT_MAX_QUEUE_FLOWS]; }; struct dpaa2_port { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 40/65] eventdev: fix port link/unlink callback return documentation 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (38 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 39/65] event/dpaa2: limit attached Rx flows per event queue Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 41/65] event/dpaa2: allow event queue link to multiple ports Prashant Gupta ` (24 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The eventdev_port_link_t, eventdev_port_link_profile_t, eventdev_port_unlink_t and eventdev_port_unlink_profile_t PMD callbacks return the number of links (or unlinks) successfully established, and a negative value on failure. This matches the rte_event_port_link() and rte_event_port_unlink() public API contract and the existing driver implementations. The Doxygen comments incorrectly stated that these callbacks "Returns 0 on success", which is misleading for PMD authors and inconsistent with the actual behaviour. Update the documentation to describe the real return semantics. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- lib/eventdev/eventdev_pmd.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/eventdev/eventdev_pmd.h b/lib/eventdev/eventdev_pmd.h index 9309dce5e1..fcf9b6922d 100644 --- a/lib/eventdev/eventdev_pmd.h +++ b/lib/eventdev/eventdev_pmd.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2016 Cavium, Inc + * Copyright 2026 NXP */ #ifndef _RTE_EVENTDEV_PMD_H_ @@ -441,7 +442,7 @@ typedef void (*eventdev_port_quiesce_t)(struct rte_eventdev *dev, void *port, * The number of links to establish * * @return - * Returns 0 on success. + * Number of links successfully established, or a negative value on failure. */ typedef int (*eventdev_port_link_t)(struct rte_eventdev *dev, void *port, const uint8_t queues[], const uint8_t priorities[], @@ -467,7 +468,7 @@ typedef int (*eventdev_port_link_t)(struct rte_eventdev *dev, void *port, * The profile ID to associate the links. * * @return - * Returns 0 on success. + * Number of links successfully established, or a negative value on failure. */ typedef int (*eventdev_port_link_profile_t)(struct rte_eventdev *dev, void *port, const uint8_t queues[], const uint8_t priorities[], @@ -486,7 +487,7 @@ typedef int (*eventdev_port_link_profile_t)(struct rte_eventdev *dev, void *port * The number of unlinks to establish * * @return - * Returns 0 on success. + * Number of unlinks successfully established, or a negative value on failure. */ typedef int (*eventdev_port_unlink_t)(struct rte_eventdev *dev, void *port, uint8_t queues[], uint16_t nb_unlinks); @@ -507,7 +508,7 @@ typedef int (*eventdev_port_unlink_t)(struct rte_eventdev *dev, void *port, * The profile ID of the associated links. * * @return - * Returns 0 on success. + * Number of unlinks successfully established, or a negative value on failure. */ typedef int (*eventdev_port_unlink_profile_t)(struct rte_eventdev *dev, void *port, uint8_t queues[], uint16_t nb_unlinks, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 41/65] event/dpaa2: allow event queue link to multiple ports 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (39 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 40/65] eventdev: fix port link/unlink callback return documentation Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 42/65] event/dpaa2: report available DPIO count and fix create cleanup Prashant Gupta ` (23 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The event queue previously stored a single owning event port and each DPCON kept a single channel_index, so a queue could be linked to only one port and the static dequeue channel could be added to only one DPIO at a time. This prevented linking the same event queue from several ports. Track the DPCON static dequeue channel per DPIO by replacing the single channel_index with ch_idx[]/dpio_idx[] arrays and a ch_idx_num count (bounded by DPAA2_DPCON_MAX_CH_IDX_NUM). On link, add a channel for the linking DPIO and record its index; on unlink, look up the channel by DPIO index and remove it, compacting the arrays. Replace the exclusive evq_info->event_port ownership with a per-queue link_num reference count and a per-port evq_map[] that resolves an event queue id to its evq_info during enqueue. This drops the old per-enqueue owner check in favour of a direct map lookup. Add range checks on event queue id in queue setup and Rx queue attach, verify the queue index matches its event_queue_id, reject linking a queue configured as single link when already linked, and return specific error codes. Lower a couple of noisy messages from ERR/WARN to WARN/DEBUG. Update the scheduler DPCI receive and drain paths to the new per-DPIO channel index tracking. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 6 +- drivers/event/dpaa2/dpaa2_eventdev.c | 207 ++++++++++++++---------- drivers/event/dpaa2/dpaa2_eventdev.h | 3 +- drivers/event/dpaa2/dpaa2_scheduler.c | 10 +- 4 files changed, 140 insertions(+), 86 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index a0b1d2abfa..f67f2283db 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -283,6 +283,8 @@ struct dpaa2_dpci_dev { struct dpaa2_queue *tx_queue; }; +#define DPAA2_DPCON_MAX_CH_IDX_NUM 16 + struct dpaa2_dpcon_dev { TAILQ_ENTRY(dpaa2_dpcon_dev) next; struct fsl_mc_io dpcon; @@ -291,7 +293,9 @@ struct dpaa2_dpcon_dev { uint32_t dpcon_id; uint16_t qbman_ch_id; uint8_t num_priorities; - uint8_t channel_index; + uint8_t ch_idx[DPAA2_DPCON_MAX_CH_IDX_NUM]; + uint16_t dpio_idx[DPAA2_DPCON_MAX_CH_IDX_NUM]; + uint8_t ch_idx_num; }; /* DPCON channel pool, shared by the net rx-interrupt path and the event PMD */ diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index cd2b00c3c9..4c20e26870 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -47,14 +47,21 @@ dpaa2_eventdev_attach_eth_rxq(const struct rte_eth_dev *dev, const struct rte_event_eth_rx_adapter_queue_conf *queue_conf) { int ret; - uint8_t ev_qid = queue_conf->ev.queue_id; - uint16_t idx = priv->evq_info[ev_qid].dpni_rxq_num; - struct dpaa2_dpcon_dev *dpcon = priv->evq_info[ev_qid].dpcon; + uint16_t ev_qid = queue_conf->ev.queue_id, idx; + struct dpaa2_dpcon_dev *dpcon; + + if (ev_qid >= priv->max_event_queues) { + DPAA2_EVENTDEV_ERR("Invalid event queue ID(%d) >= %d", + ev_qid, priv->max_event_queues); + return -EINVAL; + } + idx = priv->evq_info[ev_qid].dpni_rxq_num; if (idx >= DPAA2_EVENT_MAX_QUEUE_FLOWS) { DPAA2_EVENTDEV_ERR("Too many flows to attach eventq%d", ev_qid); return -ENOMEM; } + dpcon = priv->evq_info[ev_qid].dpcon; ret = dpaa2_eth_eventq_attach(dev, rxq_id, dpcon, queue_conf); if (ret) { DPAA2_EVENTDEV_ERR("Event queue attach failed: err(%d)", ret); @@ -114,8 +121,6 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], { struct dpaa2_port *dpaa2_portal = port; struct dpaa2_dpio_dev *dpio_dev; - struct rte_eventdev *eventdev = dpaa2_portal->eventdev; - struct dpaa2_eventdev *priv = eventdev->data->dev_private; struct dpaa2_eventq *evq_info; uint32_t queue_id, retry_count, loop, frames_to_send, i; struct qbman_swp *swp; @@ -145,13 +150,13 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], event = &ev[num_tx + loop]; queue_id = event->queue_id; if (unlikely(queue_id >= DPAA2_EVENT_MAX_QUEUES || - priv->evq_info[queue_id].event_port != dpaa2_portal)) { - DPAA2_EVENTDEV_ERR("Event queue%d is not handled by port%d", + !dpaa2_portal->evq_map[queue_id])) { + DPAA2_EVENTDEV_ERR("Event queue%d not linked to port%d", queue_id, dpaa2_portal->port_id); ret = -EINVAL; goto send_partial; } - evq_info = &priv->evq_info[queue_id]; + evq_info = dpaa2_portal->evq_map[queue_id]; if (unlikely(event->sched_type >= DPAA2_EVENTQ_LINK_CONF_MAX || !evq_info->dpci_txqs[event->sched_type])) { DPAA2_EVENTDEV_ERR("Event sched_type(%d) is not supported", @@ -606,20 +611,32 @@ dpaa2_eventdev_queue_setup(struct rte_eventdev *dev, uint8_t queue_id, const struct rte_event_queue_conf *queue_conf) { struct dpaa2_eventdev *priv = dev->data->dev_private; - struct dpaa2_eventq *evq_info = &priv->evq_info[queue_id]; + struct dpaa2_eventq *evq_info; EVENTDEV_INIT_FUNC_TRACE(); + if (queue_id >= priv->max_event_queues) { + DPAA2_EVENTDEV_ERR("Invalid queue ID(%d) >= %d", queue_id, + priv->max_event_queues); + return -EINVAL; + } + evq_info = &priv->evq_info[queue_id]; + if (queue_id != evq_info->event_queue_id) { + DPAA2_EVENTDEV_ERR("Queue index(%d) != event queue ID(%d)?", + queue_id, evq_info->event_queue_id); + return -EACCES; + } + switch (queue_conf->schedule_type) { case RTE_SCHED_TYPE_PARALLEL: case RTE_SCHED_TYPE_ATOMIC: break; default: - DPAA2_EVENTDEV_ERR("Schedule type is not supported."); - return -1; + DPAA2_EVENTDEV_ERR("Schedule type(%d) is not supported.", + queue_conf->schedule_type); + return -ENOTSUP; } evq_info->event_queue_cfg = queue_conf->event_queue_cfg; - evq_info->event_queue_id = queue_id; return 0; } @@ -657,40 +674,83 @@ dpaa2_eventdev_port_unlink(struct rte_eventdev *dev, void *port, struct dpaa2_dpio_dev *dpio_dev = NULL; struct dpaa2_eventq *evq_info; struct qbman_swp *swp; - uint8_t total_queues[DPAA2_EVENT_MAX_QUEUES]; struct dpaa2_eventq *evq_infos[DPAA2_EVENT_MAX_QUEUES]; + uint16_t pos[DPAA2_DPCON_MAX_CH_IDX_NUM], ch_idx; EVENTDEV_INIT_FUNC_TRACE(); RTE_SET_USED(dev); - if (!queues) { - queues = total_queues; + dpio_dev = dpaa2_portal->dpio_dev; + if (!dpio_dev) + return 0; + + swp = dpio_dev->sw_portal; + if (!queues) nb_unlinks = dpaa2_portal->num_linked_evq; - for (i = 0; i < nb_unlinks; i++) - queues[i] = dpaa2_portal->evq_info[i]->event_queue_id; + + for (i = 0; i < nb_unlinks; i++) { + if (!queues) { + evq_info = dpaa2_portal->evq_info[i]; + goto map_check; + } + evq_info = NULL; + for (j = 0; j < dpaa2_portal->num_linked_evq; j++) { + if (queues[i] == dpaa2_portal->evq_info[j]->event_queue_id) { + evq_info = dpaa2_portal->evq_info[j]; + break; + } + } + if (!evq_info) { + DPAA2_EVENTDEV_WARN("Event port%d doesn't handle queues[%d](%d)", + dpaa2_portal->port_id, i, queues[i]); + return -EINVAL; + } +map_check: + if (dpaa2_portal->evq_map[evq_info->event_queue_id] != evq_info) { + DPAA2_EVENTDEV_ERR("Event queue mapping[%d] mismatch.", + evq_info->event_queue_id); + return -EINVAL; + } + for (j = 0; j < evq_info->dpcon->ch_idx_num; j++) { + if (evq_info->dpcon->dpio_idx[j] == dpio_dev->index) + break; + } + if (j == evq_info->dpcon->ch_idx_num) { + DPAA2_EVENTDEV_ERR("Event queue.%d was NOT attached to dpio.%d.", + evq_info->event_queue_id, dpio_dev->index); + return -EINVAL; + } + pos[i] = j; + evq_infos[i] = evq_info; } for (i = 0; i < nb_unlinks; i++) { + evq_info = evq_infos[i]; + ch_idx = evq_info->dpcon->ch_idx[pos[i]]; + qbman_swp_push_set(swp, ch_idx, 0); + ret = dpio_remove_static_dequeue_channel(dpio_dev->dpio, + 0, dpio_dev->token, evq_info->dpcon->dpcon_id); + if (ret) { + DPAA2_EVENTDEV_ERR("Failed(%d) to remove channel (dpio.%d/dpcon.%d)", + ret, dpio_dev->index, evq_info->dpcon->dpcon_id); + break; + } + memmove(&evq_info->dpcon->ch_idx[pos[i]], + &evq_info->dpcon->ch_idx[pos[i] + 1], + evq_info->dpcon->ch_idx_num - (pos[i] + 1)); + memmove(&evq_info->dpcon->dpio_idx[pos[i]], + &evq_info->dpcon->dpio_idx[pos[i] + 1], + (evq_info->dpcon->ch_idx_num - (pos[i] + 1)) * sizeof(uint16_t)); + evq_info->dpcon->ch_idx_num--; for (j = 0; j < dpaa2_portal->num_linked_evq; j++) { - evq_info = dpaa2_portal->evq_info[j]; - if (evq_info && evq_info->event_queue_id == queues[i]) { - dpio_dev = dpaa2_portal->dpio_dev; - swp = dpio_dev->sw_portal; - qbman_swp_push_set(swp, evq_info->dpcon->channel_index, 0); - ret = dpio_remove_static_dequeue_channel(dpio_dev->dpio, - 0, dpio_dev->token, evq_info->dpcon->dpcon_id); - if (ret) - DPAA2_EVENTDEV_WARN("Failed(%d) to remove channel", ret); - evq_info->event_port = NULL; + if (dpaa2_portal->evq_info[j] == evq_info) { dpaa2_portal->evq_info[j] = NULL; - num++; break; } } - if (j == dpaa2_portal->num_linked_evq) { - DPAA2_EVENTDEV_WARN("%s: Event port%d doesn't handle queue[%d]:%d", - __func__, dpaa2_portal->port_id, i, queues[i]); - } + dpaa2_portal->evq_map[evq_info->event_queue_id] = NULL; + evq_info->link_num--; + num++; } for (i = 0; i < dpaa2_portal->num_linked_evq; i++) { @@ -714,75 +774,60 @@ dpaa2_eventdev_port_link(struct rte_eventdev *dev, void *port, uint16_t nb_links) { struct dpaa2_eventdev *priv = dev->data->dev_private; - struct dpaa2_port *dpaa2_portal = port, *ev_port; + struct dpaa2_port *dpaa2_portal = port; struct dpaa2_dpio_dev *dpio_dev = dpaa2_portal->dpio_dev; struct dpaa2_eventq *evq_info; - int ret = 0; uint16_t i; - uint8_t channel_index; + uint8_t ch_idx; + int ret = 0; EVENTDEV_INIT_FUNC_TRACE(); RTE_SET_USED(priorities); - if (dpaa2_portal->num_linked_evq > 0) { - ret = rte_event_port_unlink(dev->data->dev_id, - dpaa2_portal->port_id, NULL, 0); - if (ret) - return ret; - } - for (i = 0; i < nb_links; i++) { + if (queues[i] >= priv->max_event_queues) { + DPAA2_EVENTDEV_ERR("Event port%d: queues[%d](%d) >= %d", + dpaa2_portal->port_id, i, queues[i], priv->max_event_queues); + break; + } evq_info = &priv->evq_info[queues[i]]; - if (!evq_info->valid) { - DPAA2_EVENTDEV_WARN("%s: Event port%d.queue%d is not valid!", - __func__, dpaa2_portal->port_id, queues[i]); - return -EINVAL; + if (evq_info->link_num > 0 && + (evq_info->event_queue_cfg & RTE_EVENT_QUEUE_CFG_SINGLE_LINK)) { + DPAA2_EVENTDEV_ERR("Event queue[%d] is configured as single link", + queues[i]); + break; } - if (evq_info->event_port) { - ev_port = evq_info->event_port; - DPAA2_EVENTDEV_WARN("%s: queue%d is occupied by event port%d", - __func__, queues[i], ev_port->port_id); - return -ENODEV; + if (evq_info->dpcon->ch_idx_num >= DPAA2_DPCON_MAX_CH_IDX_NUM) { + DPAA2_EVENTDEV_ERR("Too many channel to be added with dpcon(ID=%d)", + evq_info->dpcon->dpcon_id); + break; + } + if (dpaa2_portal->evq_map[queues[i]]) { + DPAA2_EVENTDEV_ERR("Event port%d: queue%d already mapped", + dpaa2_portal->port_id, queues[i]); + break; } - } - - for (i = 0; i < nb_links; i++) { - evq_info = &priv->evq_info[queues[i]]; ret = dpio_add_static_dequeue_channel(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token, - evq_info->dpcon->dpcon_id, &channel_index); + evq_info->dpcon->dpcon_id, &ch_idx); if (ret) { DPAA2_EVENTDEV_ERR("Event port%d.queue%d static dequeue config failed(%d)", dpaa2_portal->port_id, queues[i], ret); - goto err; + break; } - - qbman_swp_push_set(dpio_dev->sw_portal, channel_index, 1); - evq_info->dpcon->channel_index = channel_index; - dpaa2_portal->evq_info[dpaa2_portal->num_linked_evq] = evq_info; - evq_info->event_port = dpaa2_portal; dpaa2_portal->num_linked_evq++; - } + evq_info->dpcon->ch_idx[evq_info->dpcon->ch_idx_num] = ch_idx; + evq_info->dpcon->dpio_idx[evq_info->dpcon->ch_idx_num] = dpio_dev->index; + evq_info->dpcon->ch_idx_num++; + evq_info->link_num++; + dpaa2_portal->evq_map[queues[i]] = evq_info; -err: - if (!ret) - return nb_links; - - nb_links = i; - for (i = 0; i < nb_links; i++) { - evq_info = &priv->evq_info[queues[i]]; - evq_info->event_port = NULL; - qbman_swp_push_set(dpio_dev->sw_portal, evq_info->dpcon->channel_index, 0); - if (dpio_remove_static_dequeue_channel(dpio_dev->dpio, - 0, dpio_dev->token, evq_info->dpcon->dpcon_id)) { - DPAA2_EVENTDEV_ERR("Event port%d.queue%d remove failed!", - dpaa2_portal->port_id, queues[i]); - } - dpaa2_portal->num_linked_evq--; + qbman_swp_push_set(dpio_dev->sw_portal, ch_idx, 1); } - return ret; + + return i; } static int @@ -795,7 +840,7 @@ dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, EVENTDEV_INIT_FUNC_TRACE(); if (dev->data->ports[port_id]) { - DPAA2_EVENTDEV_WARN("Event port%d exists!", port_id); + DPAA2_EVENTDEV_DEBUG("Event port%d exists!", port_id); dpaa2_eventdev_port_release(dev->data->ports[port_id]); } @@ -1231,7 +1276,7 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) /** TO DO: order schedule.*/ evq_info->valid = true; - evq_info->event_port = NULL; + evq_info->event_queue_id = priv->max_event_queues; priv->max_event_queues++; if (priv->max_event_queues >= DPAA2_EVENT_MAX_QUEUES) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index adeb22bda6..c0ce42c83f 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -54,7 +54,7 @@ enum { #define DPAA2_EVENTQ_LINK_CONF_MAX 4 /** Max schedule type + 1.*/ struct dpaa2_eventq { int valid; - void *event_port; + uint8_t link_num; /* DPcon device */ struct dpaa2_dpcon_dev *dpcon; /* Attached DPCI device */ @@ -80,6 +80,7 @@ struct dpaa2_port { RTE_ATOMIC(uint32_t) flushing; struct dpaa2_eventq *evq_info[DPAA2_EVENT_MAX_QUEUES]; + struct dpaa2_eventq *evq_map[DPAA2_EVENT_MAX_QUEUES]; uint8_t port_id; uint8_t num_linked_evq; uint64_t timeout_us; diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c b/drivers/event/dpaa2/dpaa2_scheduler.c index 6a4ec04aae..9e58b4253f 100644 --- a/drivers/event/dpaa2/dpaa2_scheduler.c +++ b/drivers/event/dpaa2/dpaa2_scheduler.c @@ -196,16 +196,18 @@ dpaa2_scheduler_dpci_recv(struct dpaa2_sch_dev *sch_dev, ret = dpio_add_static_dequeue_channel(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token, dpcon_dev->dpcon_id, - &dpcon_dev->channel_index); + &dpcon_dev->ch_idx[dpcon_dev->ch_idx_num]); if (ret) { DPAA2_EVENTDEV_ERR("Failure(%d) adding dpcon%d to static dq channel", ret, dpcon_dev->dpcon_id); return 0; } + dpcon_dev->dpio_idx[dpcon_dev->ch_idx_num] = dpio_dev->index; - qbman_swp_push_set(swp, dpcon_dev->channel_index, 1); + qbman_swp_push_set(swp, dpcon_dev->ch_idx[dpcon_dev->ch_idx_num], 1); sch_dev->linked[cpu] = sch_dev->port_queue_num; sch_dev->dpio_dev[cpu] = dpio_dev; + dpcon_dev->ch_idx_num++; start_dq: while (num_pkts < nb_pkts) { @@ -562,7 +564,9 @@ dpaa2_scheduler_rx_core_push_drain(struct dpaa2_sch_dev *sch_dev, if (drain_num > 0) DPAA2_EVENTDEV_WARN("Drain %d buffer(s) from core%d", drain_num, core); - qbman_swp_push_set(dpio_dev->sw_portal, dpcon_dev->channel_index, 0); + qbman_swp_push_set(dpio_dev->sw_portal, + dpcon_dev->ch_idx[dpcon_dev->ch_idx_num - 1], 0); + dpcon_dev->ch_idx_num--; if (attach_num) (*attach_num)++; ret = dpio_remove_static_dequeue_channel(dpio_dev->dpio, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 42/65] event/dpaa2: report available DPIO count and fix create cleanup 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (40 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 41/65] event/dpaa2: allow event queue link to multiple ports Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 43/65] event/dpaa2: use event port DPIO for dequeue wait Prashant Gupta ` (22 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> max_event_ports was reported as the total number of DPAA2_IO devices, including DPIOs already claimed by other users(affine portals). Add an internal helper rte_dpaa2_available_dpio_device() that counts only DPIOs with a zero reference count, and use it so the eventdev advertises the number of ports it can actually acquire. Rework dpaa2_eventdev_create() error handling. The device creation loop now iterates over a fixed range and, on any DPCI attach failure, frees the DPCON and DPCI acquired for the current event queue and breaks out instead of returning with resources leaked. A single done path releases the DPCON/DPCI of all event queues set up so far when an error occurred, and the function returns a meaningful error code rather than a fixed -EFAULT. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 15 +++++++ drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 4 ++ drivers/event/dpaa2/dpaa2_eventdev.c | 52 +++++++++++++++--------- drivers/event/dpaa2/dpaa2_eventdev.h | 23 ++++++++++- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 55dcef41d1..654472b284 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -465,6 +465,21 @@ void rte_dpaa2_free_dpio_device(struct dpaa2_dpio_dev *dpio_dev) dpaa2_put_qbman_swp(dpio_dev); } +RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_available_dpio_device) +uint16_t +rte_dpaa2_available_dpio_device(void) +{ + struct dpaa2_dpio_dev *dpio_dev = NULL; + uint16_t available_num = 0; + + TAILQ_FOREACH(dpio_dev, &dpio_dev_list, next) { + if (dpio_dev && !rte_atomic16_read(&dpio_dev->ref_count)) + available_num++; + } + + return available_num; +} + static void dpaa2_close_dpio_device(int object_id) { diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index ae0f5993d6..d28fdb03b7 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -78,4 +78,8 @@ __rte_internal void rte_dpaa2_free_dpio_device(struct dpaa2_dpio_dev *dpio_dev); +__rte_internal +uint16_t +rte_dpaa2_available_dpio_device(void); + #endif /* _DPAA2_HW_DPIO_H_ */ diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 4c20e26870..5badc17af7 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -401,7 +401,7 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS; dev_info->max_event_priority_levels = DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS; - dev_info->max_event_ports = rte_fslmc_get_device_count(DPAA2_IO); + dev_info->max_event_ports = rte_dpaa2_available_dpio_device(); if (dev_info->max_event_ports > dev_info->max_event_queues) dev_info->max_event_ports = dev_info->max_event_queues; /* we only support dpio up to number of cores */ @@ -1209,17 +1209,18 @@ static int dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) { struct rte_eventdev *eventdev; - struct dpaa2_eventdev *priv; + struct dpaa2_eventdev *priv = NULL; struct dpaa2_dpcon_dev *dpcon_dev = NULL; struct dpaa2_dpci_dev *dpci_dev = NULL; struct dpaa2_eventq *evq_info; - int ret; + int ret = 0, i; eventdev = rte_event_pmd_vdev_init(name, sizeof(struct dpaa2_eventdev), rte_socket_id(), vdev); if (!eventdev) { + ret = -ENOMEM; DPAA2_EVENTDEV_ERR("Failed to create Event device %s", name); - goto fail; + goto done; } eventdev->dev_ops = &dpaa2_eventdev_ops; @@ -1237,8 +1238,8 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) priv = eventdev->data->dev_private; memset(priv, 0, sizeof(struct dpaa2_eventdev)); - do { - evq_info = &priv->evq_info[priv->max_event_queues]; + for (i = 0; i < DPAA2_EVENT_MAX_QUEUES; i++) { + evq_info = &priv->evq_info[i]; dpcon_dev = rte_dpaa2_alloc_dpcon_dev(); if (!dpcon_dev) break; @@ -1256,10 +1257,8 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) dpaa2_eventdev_process_parallel, &evq_info->dpci_txqs[RTE_SCHED_TYPE_PARALLEL]); if (ret) { - rte_dpaa2_free_dpcon_dev(evq_info->dpcon); - rte_dpaa2_free_dpci_dev(evq_info->dpci); DPAA2_EVENTDEV_ERR("DPCI attach parallel RX failed: err(%d)", ret); - break; + goto err_break; } ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, @@ -1267,10 +1266,8 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) dpaa2_eventdev_process_atomic, &evq_info->dpci_txqs[RTE_SCHED_TYPE_ATOMIC]); if (ret) { - rte_dpaa2_free_dpcon_dev(evq_info->dpcon); - rte_dpaa2_free_dpci_dev(evq_info->dpci); DPAA2_EVENTDEV_ERR("DPCI attach atomic RX failed: err(%d)", ret); - break; + goto err_break; } /** TO DO: order schedule.*/ @@ -1279,17 +1276,32 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) evq_info->event_queue_id = priv->max_event_queues; priv->max_event_queues++; - if (priv->max_event_queues >= DPAA2_EVENT_MAX_QUEUES) - break; - } while (dpcon_dev && dpci_dev); - - DPAA2_EVENTDEV_INFO("%s eventdev created", name); + continue; +err_break: + if (evq_info->dpcon) + rte_dpaa2_free_dpcon_dev(evq_info->dpcon); + if (evq_info->dpci) + rte_dpaa2_free_dpci_dev(evq_info->dpci); + break; + } done: + if (ret && priv) { + for (i = 0; i < priv->max_event_queues; i++) { + evq_info = &priv->evq_info[i]; + if (evq_info->dpcon) + rte_dpaa2_free_dpcon_dev(evq_info->dpcon); + if (evq_info->dpci) + rte_dpaa2_free_dpci_dev(evq_info->dpci); + } + } event_dev_probing_finish(eventdev); - return 0; -fail: - return -EFAULT; + if (ret) + DPAA2_EVENTDEV_ERR("Failed(%d) to create event device(%s)", ret, name); + else + DPAA2_EVENTDEV_INFO("Create event device(%s)", name); + + return ret; } static int diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index c0ce42c83f..af1c831b92 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -8,6 +8,9 @@ #include <eventdev_pmd.h> #include <eventdev_pmd_vdev.h> #include <rte_atomic.h> +#include <rte_common.h> +#include <rte_eventdev.h> + #include <mc/fsl_dpcon.h> #include <mc/fsl_mc_sys.h> @@ -15,6 +18,7 @@ #define DPAA2_EVENT_DEFAULT_DPCI_PRIO 0 +#define DPAA2_EVENT_MAX_PORTS 16 #define DPAA2_EVENT_MAX_QUEUES 16 #define DPAA2_EVENT_MIN_DEQUEUE_TIMEOUT 1 #define DPAA2_EVENT_MAX_DEQUEUE_TIMEOUT (UINT32_MAX - 1) @@ -51,7 +55,24 @@ enum { * the ethdev to eventdev with DPAA2 devices. */ -#define DPAA2_EVENTQ_LINK_CONF_MAX 4 /** Max schedule type + 1.*/ +/* + * Size of the per-eventq dpci_txqs[] array. It is indexed directly by + * event->sched_type, so it must be (largest sched-type value) + 1. + * RTE_SCHED_TYPE_{ORDERED,ATOMIC,PARALLEL} are plain macros (0, 1, 2) with + * no upstream MAX definition, so compute the maximum explicitly here rather + * than assuming PARALLEL is numerically largest. If the sched-type values are + * ever renumbered upstream, this expression still yields the correct bound. + * + * A plain ternary max is used (not RTE_MAX): RTE_MAX expands to a GCC + * statement-expression ({ ... }), which is not a constant expression and + * cannot size an array at file scope. + */ +#define DPAA2_EVENTQ_MAX2(a, b) ((a) > (b) ? (a) : (b)) +#define DPAA2_EVENTQ_LINK_CONF_MAX \ + (DPAA2_EVENTQ_MAX2(RTE_SCHED_TYPE_ORDERED, \ + DPAA2_EVENTQ_MAX2(RTE_SCHED_TYPE_ATOMIC, \ + RTE_SCHED_TYPE_PARALLEL)) + 1) + struct dpaa2_eventq { int valid; uint8_t link_num; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 43/65] event/dpaa2: use event port DPIO for dequeue wait 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (41 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 42/65] event/dpaa2: report available DPIO count and fix create cleanup Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 44/65] bus/fslmc: consolidate DPIO interrupt setup and bound coalescing Prashant Gupta ` (21 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> dpaa2_eventdev_dequeue_wait() cleared the interrupt status and armed epoll_wait() using the per-lcore portal and DPIO (DPAA2_PER_LCORE_PORTAL / DPAA2_PER_LCORE_DPIO). Those per-lcore handles are only valid on the polling path and do not correspond to the DPIO backing the event port, so the interrupt fd waited on could belong to the wrong portal. Pass the event port's dpio_dev into dpaa2_eventdev_dequeue_wait() and use its software portal and epoll fd, matching the DPIO actually used by the dequeue burst. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 5badc17af7..be23dbf4dc 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -230,15 +230,13 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], return num_tx; } -static void dpaa2_eventdev_dequeue_wait(uint64_t timeout_ticks) +static void dpaa2_eventdev_dequeue_wait(struct dpaa2_dpio_dev *dpio_dev, + uint64_t timeout_ticks) { struct epoll_event epoll_ev; - qbman_swp_interrupt_clear_status(DPAA2_PER_LCORE_PORTAL, - QBMAN_SWP_INTERRUPT_DQRI); - - epoll_wait(DPAA2_PER_LCORE_DPIO->epoll_fd, - &epoll_ev, 1, timeout_ticks); + qbman_swp_interrupt_clear_status(dpio_dev->sw_portal, QBMAN_SWP_INTERRUPT_DQRI); + epoll_wait(dpio_dev->epoll_fd, &epoll_ev, 1, timeout_ticks); } static void dpaa2_eventdev_process_parallel(struct dpaa2_dpio_dev *dpio_dev, @@ -316,7 +314,7 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], */ qbman_swp_dqrr_consume(swp, NULL); if (!num_pkts && timeout_ticks) { - dpaa2_eventdev_dequeue_wait(timeout_ticks); + dpaa2_eventdev_dequeue_wait(dpio_dev, timeout_ticks); timeout_ticks = 0; continue; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 44/65] bus/fslmc: consolidate DPIO interrupt setup and bound coalescing 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (42 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 43/65] event/dpaa2: use event port DPIO for dequeue wait Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 45/65] event/dpaa2: honor configured dequeue timeout Prashant Gupta ` (20 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Move the DPIO DQRI interrupt setup into rte_dpaa2_alloc_dpio_device() so that both the event PMD and the portal-affine path share a single entry point. The allocator now takes the interrupt-enable flag, the DQRR coalescing threshold and the target CPU, and it optionally pins the portal IRQ to that core. This removes the duplicated interrupt init that previously lived in dpaa2_configure_stashing(). Validate the coalescing configuration on the way in: - The DQRR threshold is capped at the portal DQRR ring depth minus one (DPAA2_PORTAL_INTR_THRESH_MAX). An out-of-range value from the DPAA2_PORTAL_INTR_THRESHOLD environment variable or the caller is rejected and coalescing is disabled. - qbman_swp_dqrr_thrshld_write() clamps the threshold to the ring size, and qbman_swp_intr_timeout_write() clamps the ITP tick to QBMAN_CINH_SWP_ITPR_MAX (12-bit field). Also clean up the QBMan portal interrupt helpers: - Add QBMAN_SWP_INTERRUPT_ALL and use it when clearing the portal interrupt status instead of the bare 0xffffffff mask. - Fix qbman_swp_interrupt_set_inhibit() to write the single LSB inhibit bit as described by the reference manual rather than an all-ones mask. - Rename the misleading "mask" parameters of the threshold and timeout writers to "threshold" and "qbman_tick". Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 103 ++++++++---------- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 5 +- .../fslmc/qbman/include/fsl_qbman_portal.h | 12 +- drivers/bus/fslmc/qbman/qbman_portal.c | 22 +++- drivers/bus/fslmc/qbman/qbman_sys.h | 4 +- drivers/event/dpaa2/dpaa2_eventdev.c | 3 +- 6 files changed, 79 insertions(+), 70 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 654472b284..4affd4e0b4 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -181,7 +181,7 @@ dpaa2_dpio_affine_intr_to_core(int32_t dpio_id) */ RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_init) int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, - int timeout, bool build_epoll) + int timeout, bool build_epoll) { int eventfd, dpio_epoll_fd, ret; struct epoll_event epoll_ev; @@ -191,13 +191,12 @@ int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, ret = rte_dpaa2_intr_enable(dpio_dev->intr_handle, 0); if (ret) { - DPAA2_BUS_ERR("Interrupt registration failed"); - return -1; + DPAA2_BUS_ERR("Failed(%d) to enable dpio interrupt", ret); + return ret; } - qbman_swp_interrupt_set_trigger(dpio_dev->sw_portal, - QBMAN_SWP_INTERRUPT_DQRI); - qbman_swp_interrupt_clear_status(dpio_dev->sw_portal, 0xffffffff); + qbman_swp_interrupt_set_trigger(dpio_dev->sw_portal, QBMAN_SWP_INTERRUPT_DQRI); + qbman_swp_interrupt_clear_status(dpio_dev->sw_portal, QBMAN_SWP_INTERRUPT_ALL); qbman_swp_interrupt_set_inhibit(dpio_dev->sw_portal, 0); qbman_swp_dqrr_thrshld_write(dpio_dev->sw_portal, threshold); qbman_swp_intr_timeout_write(dpio_dev->sw_portal, timeout); @@ -214,7 +213,7 @@ int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, if (dpio_epoll_fd < 0) { DPAA2_BUS_ERR("epoll_create failed"); rte_dpaa2_intr_disable(dpio_dev->intr_handle, 0); - return -1; + return -errno; } eventfd = rte_intr_fd_get(dpio_dev->intr_handle); @@ -256,7 +255,7 @@ void dpaa2_dpio_intr_deinit(struct dpaa2_dpio_dev *dpio_dev) } static int -dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx) +dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) { int sdest, ret; @@ -276,29 +275,6 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id, bool ethrx return ret; } -#ifdef RTE_EVENT_DPAA2 - /* Only the event PMD's portal is set up here (coalesced DQRI, private - * epoll). The net rx-interrupt portal (ethrx) is configured by the net - * PMD in rx_queue_intr_enable, so do not touch it here. - */ - if (!ethrx) { - int threshold = 3, timeout = 0xFF; - - if (getenv("DPAA2_PORTAL_INTR_THRESHOLD")) - threshold = atoi(getenv("DPAA2_PORTAL_INTR_THRESHOLD")); - if (getenv("DPAA2_PORTAL_INTR_TIMEOUT")) - sscanf(getenv("DPAA2_PORTAL_INTR_TIMEOUT"), "%x", &timeout); - - if (dpaa2_dpio_intr_init(dpio_dev, threshold, timeout, true)) { - DPAA2_BUS_ERR("Interrupt registration failed for dpio"); - return -1; - } - dpaa2_affine_dpio_intr_to_respective_core(dpio_dev->hw_id, cpu_id); - } -#else - RTE_SET_USED(ethrx); -#endif - return 0; } @@ -316,25 +292,18 @@ static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) dpaa2_dpio_intr_deinit(dpio_dev); dpio_dev->cpu_affine = -1; rte_atomic_store_explicit(&dpio_dev->ref_count, 0, - rte_memory_order_release); + rte_memory_order_release); } } static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(bool ethrx) { - struct dpaa2_dpio_dev *dpio_dev = NULL; - int cpu_id; - int ret; - - /* Get DPIO dev handle from list using index */ - TAILQ_FOREACH(dpio_dev, &dpio_dev_list, next) { - uint16_t expected = 0; + struct dpaa2_dpio_dev *dpio_dev; + /* Set the Stashing Destination */ + int cpu_id = dpaa2_get_core_id(), ret; - if (rte_atomic_compare_exchange_strong_explicit(&dpio_dev->ref_count, - &expected, 1, rte_memory_order_acquire, - rte_memory_order_relaxed)) - break; - } + dpio_dev = rte_dpaa2_alloc_dpio_device((ethrx && cpu_id >= 0) ? + true : false, DPAA2_PORTAL_INTR_COALESC_DISABLE, cpu_id); if (!dpio_dev) { DPAA2_BUS_ERR("No software portal resource left"); return NULL; @@ -343,18 +312,16 @@ static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(bool ethrx) DPAA2_BUS_DEBUG("New Portal %p (%d) affined thread - %u", dpio_dev, dpio_dev->index, rte_gettid()); - /* Set the Stashing Destination */ - cpu_id = dpaa2_get_core_id(); if (cpu_id < 0) { DPAA2_BUS_WARN("Thread not affined to a single core"); if (dpaa2_svr_family != SVR_LX2160A) qbman_swp_update(dpio_dev->sw_portal, 1); } else { - ret = dpaa2_configure_stashing(dpio_dev, cpu_id, ethrx); + ret = dpaa2_configure_stashing(dpio_dev, cpu_id); if (ret) { DPAA2_BUS_ERR("dpaa2_configure_stashing failed"); rte_atomic_store_explicit(&dpio_dev->ref_count, 0, - rte_memory_order_release); + rte_memory_order_release); return NULL; } } @@ -426,9 +393,13 @@ static void dpaa2_portal_finish(void *arg) RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_alloc_dpio_device) struct dpaa2_dpio_dev * -rte_dpaa2_alloc_dpio_device(int32_t cpu_affine) +rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, int32_t cpu_affine) { struct dpaa2_dpio_dev *dpio_dev = NULL; +#ifdef RTE_EVENT_DPAA2 + int ret, timeout = 0xff; + char *env; +#endif uint16_t expected = 0; /* Get DPIO dev handle from list using index */ @@ -442,18 +413,35 @@ rte_dpaa2_alloc_dpio_device(int32_t cpu_affine) DPAA2_BUS_ERR("No software portal resource left"); return NULL; } - - DPAA2_BUS_DEBUG("New Portal %p (%d) affined thread - %u", - dpio_dev, dpio_dev->index, rte_gettid()); - -#ifdef RTE_EVENT_DPAA2 - if (dpaa2_dpio_intr_init(dpio_dev, 1, 0, false)) { - DPAA2_BUS_ERR("Interrupt registration failed for dpio"); + #ifdef RTE_EVENT_DPAA2 + if (!isr) + goto quit; + env = getenv("DPAA2_PORTAL_INTR_THRESHOLD"); + if (env) + threshold = atoi(env); + if (threshold > DPAA2_PORTAL_INTR_THRESH_MAX) { + DPAA2_BUS_ERR("Invalid threshold(%d) from %s", + threshold, env ? "environment" : "parameter"); + threshold = DPAA2_PORTAL_INTR_COALESC_DISABLE; + } + env = getenv("DPAA2_PORTAL_INTR_TIMEOUT"); + if (env) + sscanf(env, "%x", &timeout); + ret = dpaa2_dpio_intr_init(dpio_dev, threshold, timeout, true); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to init DPIO interrupt", ret); rte_atomic_store_explicit(&dpio_dev->ref_count, 0, rte_memory_order_release); return NULL; } + if (cpu_affine >= 0) + dpaa2_affine_dpio_intr_to_respective_core(dpio_dev->hw_id, cpu_affine); +quit: +#else + RTE_SET_USED(isr); + RTE_SET_USED(threshold); #endif + dpio_dev->cpu_affine = cpu_affine; return dpio_dev; @@ -473,7 +461,8 @@ rte_dpaa2_available_dpio_device(void) uint16_t available_num = 0; TAILQ_FOREACH(dpio_dev, &dpio_dev_list, next) { - if (dpio_dev && !rte_atomic16_read(&dpio_dev->ref_count)) + if (dpio_dev && !rte_atomic_load_explicit(&dpio_dev->ref_count, + rte_memory_order_acquire)) available_num++; } diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index d28fdb03b7..0d0894572a 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -19,6 +19,9 @@ struct dpaa2_io_portal_t { struct dpaa2_dpio_dev *ethrx_dpio_dev; }; +#define DPAA2_PORTAL_INTR_COALESC_DISABLE 0 +#define DPAA2_PORTAL_INTR_THRESH_MAX (qbman_swp_portal_dqrr_size(NULL) - 1) + /*! Global per thread DPIO portal */ RTE_DECLARE_PER_LCORE(struct dpaa2_io_portal_t, _dpaa2_io); @@ -72,7 +75,7 @@ dpaa2_free_eq_descriptors(void); __rte_internal struct dpaa2_dpio_dev * -rte_dpaa2_alloc_dpio_device(int32_t cpu_affine); +rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, int32_t cpu_affine); __rte_internal void diff --git a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h index fb1c6046ae..7855172074 100644 --- a/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h +++ b/drivers/bus/fslmc/qbman/include/fsl_qbman_portal.h @@ -92,6 +92,10 @@ const struct qbman_swp_desc *qbman_swp_get_desc(struct qbman_swp *p); /* Volatile dequeue command interrupt */ #define QBMAN_SWP_INTERRUPT_VDCI ((uint32_t)0x00000020) +#define QBMAN_SWP_INTERRUPT_ALL \ + (QBMAN_SWP_INTERRUPT_EQRI | QBMAN_SWP_INTERRUPT_EQDI | \ + QBMAN_SWP_INTERRUPT_DQRI | QBMAN_SWP_INTERRUPT_RCRI | \ + QBMAN_SWP_INTERRUPT_RCDI | QBMAN_SWP_INTERRUPT_VDCI) /** * qbman_swp_interrupt_get_vanish() - Get the data in software portal * interrupt status disable register. @@ -138,9 +142,9 @@ uint32_t qbman_swp_dqrr_thrshld_read_status(struct qbman_swp *p); * qbman_swp_dqrr_thrshld_write() - Set the data in software portal * DQRR interrupt threshold register. * @p: the given software portal object. - * @mask: The value to set in SWP_DQRR_ITR register. + * @threshold: The value to set in SWP_DQRR_ITR register. */ -void qbman_swp_dqrr_thrshld_write(struct qbman_swp *p, uint32_t mask); +void qbman_swp_dqrr_thrshld_write(struct qbman_swp *p, uint32_t threshold); /** * qbman_swp_intr_timeout_read_status() - Get the data in software portal @@ -153,9 +157,9 @@ uint32_t qbman_swp_intr_timeout_read_status(struct qbman_swp *p); * qbman_swp_intr_timeout_write() - Set the data in software portal * Interrupt Time-Out period register. * @p: the given software portal object. - * @mask: The value to set in SWP_ITPR register. + * @qbman_tick: The value to set in SWP_ITPR register. */ -void qbman_swp_intr_timeout_write(struct qbman_swp *p, uint32_t mask); +void qbman_swp_intr_timeout_write(struct qbman_swp *p, uint32_t qbman_tick); /** * qbman_swp_interrupt_get_trigger() - Get the data in software portal diff --git a/drivers/bus/fslmc/qbman/qbman_portal.c b/drivers/bus/fslmc/qbman/qbman_portal.c index 307c0e3d24..6a027b4aec 100644 --- a/drivers/bus/fslmc/qbman/qbman_portal.c +++ b/drivers/bus/fslmc/qbman/qbman_portal.c @@ -447,9 +447,14 @@ uint32_t qbman_swp_dqrr_thrshld_read_status(struct qbman_swp *p) return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_DQRR_ITR); } -void qbman_swp_dqrr_thrshld_write(struct qbman_swp *p, uint32_t mask) +void qbman_swp_dqrr_thrshld_write(struct qbman_swp *p, uint32_t threshold) { - qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_DQRR_ITR, mask); + if (threshold >= p->dqrr.dqrr_size) { + pr_warn("Invalid threshold(%d) >= DRQQ size(%d)", + threshold, p->dqrr.dqrr_size); + threshold = p->dqrr.dqrr_size - 1; + } + qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_DQRR_ITR, threshold); } uint32_t qbman_swp_intr_timeout_read_status(struct qbman_swp *p) @@ -457,9 +462,14 @@ uint32_t qbman_swp_intr_timeout_read_status(struct qbman_swp *p) return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ITPR); } -void qbman_swp_intr_timeout_write(struct qbman_swp *p, uint32_t mask) +void qbman_swp_intr_timeout_write(struct qbman_swp *p, uint32_t qbman_tick) { - qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ITPR, mask); + if (qbman_tick > QBMAN_CINH_SWP_ITPR_MAX) { + pr_warn("Invalid tick(%d) > MAX ISR time-out period(%d)", + qbman_tick, QBMAN_CINH_SWP_ITPR_MAX); + qbman_tick = QBMAN_CINH_SWP_ITPR_MAX; + } + qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ITPR, qbman_tick); } uint32_t qbman_swp_interrupt_get_trigger(struct qbman_swp *p) @@ -480,8 +490,8 @@ int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p) RTE_EXPORT_INTERNAL_SYMBOL(qbman_swp_interrupt_set_inhibit) void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit) { - qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IIR, - inhibit ? 0xffffffff : 0); + /** RM 4.3.2.1.32.4, LSB bit interrupt inhibited*/ + qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IIR, inhibit ? 1 : 0); } /***********************/ diff --git a/drivers/bus/fslmc/qbman/qbman_sys.h b/drivers/bus/fslmc/qbman/qbman_sys.h index 61f817c477..8a8018943a 100644 --- a/drivers/bus/fslmc/qbman/qbman_sys.h +++ b/drivers/bus/fslmc/qbman/qbman_sys.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. - * Copyright 2019-2020 NXP + * Copyright 2019-2020, 2026 NXP */ /* qbman_sys_decl.h and qbman_sys.h are the two platform-specific files in the * driver. They are only included via qbman_private.h, which is itself a @@ -47,6 +47,8 @@ #define QBMAN_CINH_SWP_IIR 0xec0 #define QBMAN_CINH_SWP_ITPR 0xf40 +#define QBMAN_CINH_SWP_ITPR_MAX ((1 << 12) - 1) + /* CENA register offsets */ #define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((uint32_t)(n) << 6)) #define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((uint32_t)(n) << 6)) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index be23dbf4dc..30a3119e62 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -849,7 +849,8 @@ dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, return -ENOMEM; } - portal->dpio_dev = rte_dpaa2_alloc_dpio_device(-1); + portal->dpio_dev = rte_dpaa2_alloc_dpio_device(true, + DPAA2_PORTAL_INTR_COALESC_DISABLE, -1); if (!portal->dpio_dev) { rte_free(portal); return -ENODEV; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 45/65] event/dpaa2: honor configured dequeue timeout 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (43 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 44/65] bus/fslmc: consolidate DPIO interrupt setup and bound coalescing Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 46/65] bus/fslmc: use EAL API for DPIO interrupt Prashant Gupta ` (19 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The dequeue timeout handling used a fixed 1ms-per-tick scale and a hardcoded DPAA2_EVENT_PORT_DEQUEUE_TIMEOUT_NS default, and reported that constant from info_get() regardless of the value the application configured. It also passed raw timeout_ticks straight to epoll_wait(), which expects a value in milliseconds. Convert timeouts using the timer frequency. Cache rte_get_timer_hz() in priv->event_hz at configure time, compute timeout_ticks in timeout_ticks() from the requested ns, and convert ticks back to milliseconds before calling epoll_wait(). info_get() now reports the configured dequeue_timeout_ns, and configure() no longer overrides a zero timeout with the removed default constant. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 36 ++++++++++++++++------------ drivers/event/dpaa2/dpaa2_eventdev.h | 2 +- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 30a3119e62..592b3bf4a4 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -231,12 +231,12 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], } static void dpaa2_eventdev_dequeue_wait(struct dpaa2_dpio_dev *dpio_dev, - uint64_t timeout_ticks) + uint32_t timeout_ms) { struct epoll_event epoll_ev; qbman_swp_interrupt_clear_status(dpio_dev->sw_portal, QBMAN_SWP_INTERRUPT_DQRI); - epoll_wait(dpio_dev->epoll_fd, &epoll_ev, 1, timeout_ticks); + epoll_wait(dpio_dev->epoll_fd, &epoll_ev, 1, timeout_ms); } static void dpaa2_eventdev_process_parallel(struct dpaa2_dpio_dev *dpio_dev, @@ -274,10 +274,12 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], const struct qbman_result *dq; struct dpaa2_dpio_dev *dpio_dev; struct dpaa2_port *dpaa2_portal = port; + struct dpaa2_eventdev *priv; struct qbman_swp *swp; const struct qbman_fd *fd; struct dpaa2_queue *rxq; uint16_t num_pkts = 0, i = 0; + uint32_t timeout_ms; if (unlikely(dpaa2_portal->port_atomic)) rte_spinlock_lock(&dpaa2_portal->port_lock); @@ -287,6 +289,7 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], goto quit; swp = dpio_dev->sw_portal; + priv = dpaa2_portal->eventdev->data->dev_private; /* Check if there are atomic contexts to be released */ @@ -305,6 +308,10 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], i++; } dpio_dev->dpaa2_held_bufs.dqrr_held = 0; + if (timeout_ticks) + timeout_ms = timeout_ticks * 1000 / priv->event_hz; + else + timeout_ms = priv->dequeue_timeout_ns / (1000 * 1000); do { dq = qbman_swp_dqrr_next(swp); @@ -313,9 +320,9 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], * the DQRR consume vector before leaving it idle. */ qbman_swp_dqrr_consume(swp, NULL); - if (!num_pkts && timeout_ticks) { - dpaa2_eventdev_dequeue_wait(dpio_dev, timeout_ticks); - timeout_ticks = 0; + if (!num_pkts && timeout_ms) { + dpaa2_eventdev_dequeue_wait(dpio_dev, timeout_ms); + timeout_ms = 0; continue; } goto quit; @@ -390,8 +397,7 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, DPAA2_EVENT_MIN_DEQUEUE_TIMEOUT; dev_info->max_dequeue_timeout_ns = DPAA2_EVENT_MAX_DEQUEUE_TIMEOUT; - dev_info->dequeue_timeout_ns = - DPAA2_EVENT_PORT_DEQUEUE_TIMEOUT_NS; + dev_info->dequeue_timeout_ns = priv->dequeue_timeout_ns; dev_info->max_event_queues = priv->max_event_queues; dev_info->max_event_queue_flows = DPAA2_EVENT_MAX_QUEUE_FLOWS; @@ -437,6 +443,7 @@ dpaa2_eventdev_configure(const struct rte_eventdev *dev) priv->nb_event_port_dequeue_depth = conf->nb_event_port_dequeue_depth; priv->nb_event_port_enqueue_depth = conf->nb_event_port_enqueue_depth; priv->event_dev_cfg = conf->event_dev_cfg; + priv->event_hz = rte_get_timer_hz(); /* Check dequeue timeout method is per dequeue or global */ if (priv->event_dev_cfg & RTE_EVENT_DEV_CFG_PER_DEQUEUE_TIMEOUT) { @@ -446,14 +453,11 @@ dpaa2_eventdev_configure(const struct rte_eventdev *dev) */ priv->dequeue_timeout_ns = 0; - } else if (conf->dequeue_timeout_ns == 0) { - priv->dequeue_timeout_ns = DPAA2_EVENT_PORT_DEQUEUE_TIMEOUT_NS; } else { priv->dequeue_timeout_ns = conf->dequeue_timeout_ns; } - DPAA2_EVENTDEV_DEBUG("Configured eventdev devid=%d", - dev->data->dev_id); + DPAA2_EVENTDEV_DEBUG("Configured eventdev devid=%d", dev->data->dev_id); return 0; } @@ -869,14 +873,16 @@ dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, static int dpaa2_eventdev_timeout_ticks(struct rte_eventdev *dev, uint64_t ns, - uint64_t *timeout_ticks) + uint64_t *timeout_ticks) { - uint32_t scale = 1000 * 1000; + struct dpaa2_eventdev *priv = dev->data->dev_private; EVENTDEV_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); - *timeout_ticks = ns / scale; + if (!priv->event_hz) + priv->event_hz = rte_get_timer_hz(); + + *timeout_ticks = ns * priv->event_hz / 1000000000ULL; return 0; } diff --git a/drivers/event/dpaa2/dpaa2_eventdev.h b/drivers/event/dpaa2/dpaa2_eventdev.h index af1c831b92..30911382f3 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.h +++ b/drivers/event/dpaa2/dpaa2_eventdev.h @@ -22,7 +22,6 @@ #define DPAA2_EVENT_MAX_QUEUES 16 #define DPAA2_EVENT_MIN_DEQUEUE_TIMEOUT 1 #define DPAA2_EVENT_MAX_DEQUEUE_TIMEOUT (UINT32_MAX - 1) -#define DPAA2_EVENT_PORT_DEQUEUE_TIMEOUT_NS 100UL #define DPAA2_EVENT_MAX_QUEUE_FLOWS 1024 #define DPAA2_EVENT_MAX_QUEUE_PRIORITY_LEVELS 8 #define DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS 0 @@ -124,6 +123,7 @@ struct dpaa2_eventdev { uint32_t nb_event_port_dequeue_depth; uint32_t nb_event_port_enqueue_depth; uint32_t event_dev_cfg; + uint64_t event_hz; }; int test_eventdev_dpaa2(void); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 46/65] bus/fslmc: use EAL API for DPIO interrupt 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (44 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 45/65] event/dpaa2: honor configured dequeue timeout Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 47/65] bus/fslmc: defer DPIO interrupt setup and bind portal to worker core Prashant Gupta ` (18 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPIO interrupt path created a private epoll instance with the raw epoll_create/epoll_ctl/epoll_wait syscalls and cached its fd in dpaa2_dpio_dev::epoll_fd. This duplicated the epoll bookkeeping already provided by the EAL interrupt handle and split the interrupt state across two owners. Switch to the EAL rte_epoll wrappers. dpaa2_dpio_intr_init() now arms the interrupt handle's epoll event via rte_epoll_ctl(), dpaa2_dpio_intr_deinit() removes it, and the event PMD dequeue wait uses rte_epoll_wait() on the handle's epoll fd. The now redundant epoll_fd field is removed from struct dpaa2_dpio_dev. While converting, tidy the init/deinit error handling to use goto labels so the interrupt is disabled and the epoll fd closed on every failure path. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 58 ++++++++++++++++-------- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 - drivers/event/dpaa2/dpaa2_eventdev.c | 7 ++- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 4affd4e0b4..e95345627d 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -184,7 +184,7 @@ int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, int timeout, bool build_epoll) { int eventfd, dpio_epoll_fd, ret; - struct epoll_event epoll_ev; + struct rte_epoll_event *epoll_ev; if (dpio_dev->intr_enabled) return 0; @@ -201,8 +201,6 @@ int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, qbman_swp_dqrr_thrshld_write(dpio_dev->sw_portal, threshold); qbman_swp_intr_timeout_write(dpio_dev->sw_portal, timeout); - dpio_dev->epoll_fd = -1; - /* The event PMD dequeues by sleeping on a private epoll instance owned * by the portal, so build it here. The net rx-queue-interrupt path * exposes the raw eventfd through the generic ethdev API and waits on @@ -212,45 +210,65 @@ int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, dpio_epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (dpio_epoll_fd < 0) { DPAA2_BUS_ERR("epoll_create failed"); - rte_dpaa2_intr_disable(dpio_dev->intr_handle, 0); - return -errno; + ret = -errno; + goto int_disable_err; } eventfd = rte_intr_fd_get(dpio_dev->intr_handle); - epoll_ev.events = EPOLLIN | EPOLLPRI | EPOLLET; - epoll_ev.data.fd = eventfd; - - ret = epoll_ctl(dpio_epoll_fd, EPOLL_CTL_ADD, eventfd, &epoll_ev); + if (eventfd < 0) { + ret = eventfd; + goto epoll_close_err; + } + epoll_ev = rte_intr_elist_index_get(dpio_dev->intr_handle, 0); + if (rte_atomic_load_explicit(&epoll_ev->status, + rte_memory_order_relaxed) != RTE_EPOLL_INVALID) { + DPAA2_BUS_ERR("Event already been added."); + ret = -EEXIST; + goto epoll_close_err; + } + epoll_ev->epdata.event = EPOLLIN | EPOLLPRI | EPOLLET; + ret = rte_epoll_ctl(dpio_epoll_fd, EPOLL_CTL_ADD, eventfd, epoll_ev); if (ret < 0) { - DPAA2_BUS_ERR("epoll_ctl failed"); - rte_dpaa2_intr_disable(dpio_dev->intr_handle, 0); - close(dpio_epoll_fd); - return -1; + DPAA2_BUS_ERR("Epoll control add failed(%d)", ret); + goto epoll_close_err; } - dpio_dev->epoll_fd = dpio_epoll_fd; } dpio_dev->intr_enabled = 1; return 0; + +epoll_close_err: + close(dpio_epoll_fd); +int_disable_err: + rte_dpaa2_intr_disable(dpio_dev->intr_handle, 0); + return ret; } RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_deinit) void dpaa2_dpio_intr_deinit(struct dpaa2_dpio_dev *dpio_dev) { - int ret; + int ret, epfd; + struct rte_epoll_event *epoll_ev; if (!dpio_dev->intr_enabled) return; + epoll_ev = rte_intr_elist_index_get(dpio_dev->intr_handle, 0); + if (rte_atomic_load_explicit(&epoll_ev->status, + rte_memory_order_relaxed) != RTE_EPOLL_INVALID) { + epoll_ev->epdata.event = EPOLLIN | EPOLLPRI | EPOLLET; + epfd = epoll_ev->epfd; + ret = rte_epoll_ctl(epfd, EPOLL_CTL_DEL, epoll_ev->fd, epoll_ev); + if (ret < 0) + DPAA2_BUS_ERR("Epoll control delete failed(%d)", ret); + close(epfd); + } + ret = rte_dpaa2_intr_disable(dpio_dev->intr_handle, 0); if (ret) - DPAA2_BUS_ERR("DPIO interrupt disable failed"); + DPAA2_BUS_ERR("DPIO interrupt disable failed(%d)", ret); - if (dpio_dev->epoll_fd >= 0) { - close(dpio_dev->epoll_fd); - dpio_dev->epoll_fd = -1; - } dpio_dev->intr_enabled = 0; } diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index f67f2283db..52ec660fb9 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -133,7 +133,6 @@ struct dpaa2_dpio_dev { /**< Physical address of Cache Inhibit Area */ uintptr_t ci_size; /**< Size of the CI region */ struct rte_intr_handle *intr_handle; /* Interrupt related info */ - int32_t epoll_fd; /**< File descriptor created for interrupt polling */ int32_t hw_id; /**< An unique ID of this DPIO device instance */ uint8_t intr_enabled; /**< DQRI portal interrupt already set up */ int32_t cpu_affine; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 592b3bf4a4..f4dbf47b18 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -233,10 +233,13 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], static void dpaa2_eventdev_dequeue_wait(struct dpaa2_dpio_dev *dpio_dev, uint32_t timeout_ms) { - struct epoll_event epoll_ev; + int ret; + struct rte_epoll_event *epoll_event; qbman_swp_interrupt_clear_status(dpio_dev->sw_portal, QBMAN_SWP_INTERRUPT_DQRI); - epoll_wait(dpio_dev->epoll_fd, &epoll_ev, 1, timeout_ms); + epoll_event = rte_intr_elist_index_get(dpio_dev->intr_handle, 0); + ret = rte_epoll_wait(epoll_event->epfd, epoll_event, 1, timeout_ms); + DPAA2_PMD_DP_DEBUG("%s: poll return(%d)", __func__, ret); } static void dpaa2_eventdev_process_parallel(struct dpaa2_dpio_dev *dpio_dev, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 47/65] bus/fslmc: defer DPIO interrupt setup and bind portal to worker core 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (45 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 46/65] bus/fslmc: use EAL API for DPIO interrupt Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 48/65] bus/fslmc: move Tx SG mempool to fslmc bus Prashant Gupta ` (17 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rework the DPIO software-portal interrupt handling so that a portal is only wired to a VFIO eventfd IRQ when it is actually used, and bind the portal's IRQ, CPU governor and stashing to the worker core on first touch or worker core change rather than at create time. VFIO interrupt lookup: - rte_dpaa2_vfio_setup_intr() now takes a flag and returns the matched interrupt index (or a negative errno) instead of hard-coding index 0 and the eventfd type. It skips vectors that do not advertise the requested flag instead of failing on the first one. - dpaa2_dpio_intr_init() calls it with VFIO_IRQ_INFO_EVENTFD, stores the resolved intr_index in the dpio_dev, and enables/disables the interrupt using that index. The intr handle allocation and one-shot setup are removed from dpaa2_create_dpio_device(); the dpio_dev now caches vfio_fd and num_irqs for the lazy setup. Per-core binding helpers: - dpaa2_dpio_intr_affinity_set() locates the dpio.<id> IRQ in /proc/interrupts (exact-token match so dpio.17 does not match dpio.170) and writes the CPU to smp_affinity_list, returning an error code instead of the old void best-effort helper. - dpaa2_dpio_affine_intr_to_core() now takes the dpio_dev and uses the new setter. - dpaa2_dpio_cpufreq_governor() saves the per-CPU scaling_governor, forces "performance", and can restore all saved governors. - dpaa2_configure_stashing() is exported as dpaa2_dpio_configure_stashing() and its errors are propagated. Event PMD binding: - On the first dequeue on a new core or core change, the event port pins the portal IRQ to that core, sets the performance governor and configures stashing. Governors are restored in dpaa2_eventdev_close(). - Mark the port_atomic branch as unlikely on the enqueue/dequeue hot path. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/fslmc_vfio.c | 34 ++- drivers/bus/fslmc/fslmc_vfio.h | 4 +- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 297 ++++++++++++++++------- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 11 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 3 + drivers/event/dpaa2/dpaa2_eventdev.c | 29 ++- drivers/net/dpaa2/dpaa2_ethdev.c | 2 +- 7 files changed, 266 insertions(+), 114 deletions(-) diff --git a/drivers/bus/fslmc/fslmc_vfio.c b/drivers/bus/fslmc/fslmc_vfio.c index 4897d7a78b..887a68ab32 100644 --- a/drivers/bus/fslmc/fslmc_vfio.c +++ b/drivers/bus/fslmc/fslmc_vfio.c @@ -1509,41 +1509,35 @@ int rte_dpaa2_intr_disable(struct rte_intr_handle *intr_handle, int index) return ret; } -/* set up interrupt support (but not enable interrupts) */ +/* Set up interrupt with flag, return interrupt index in success, minus in failure. */ int rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, - int vfio_dev_fd, - int num_irqs) + int vfio_dev_fd, int num_irqs, uint32_t flag) { - int i, ret; + int i, ret, fd; - /* start from MSI-X interrupt type */ + /* Find interrupt with given flag. */ for (i = 0; i < num_irqs; i++) { struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) }; - int fd = -1; irq_info.index = i; ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); if (ret < 0) { - DPAA2_BUS_ERR("Cannot get IRQ(%d) info, error %i (%s)", - i, errno, strerror(errno)); - return ret; + DPAA2_BUS_ERR("Failed(%d) to get IRQ(%d) info (%s)", + -errno, i, strerror(errno)); + continue; } - /* if this vector cannot be used with eventfd, - * fail if we explicitly - * specified interrupt type, otherwise continue - */ - if ((irq_info.flags & VFIO_IRQ_INFO_EVENTFD) == 0) + if (!(irq_info.flags & flag)) continue; /* set up an eventfd for interrupts */ fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); if (fd < 0) { - DPAA2_BUS_ERR("Cannot set up eventfd, error %i (%s)", - errno, strerror(errno)); - return fd; + DPAA2_BUS_ERR("Cannot set up eventfd, error %d (%s)", + -errno, strerror(errno)); + return -errno; } if (rte_intr_fd_set(intr_handle, fd)) @@ -1555,7 +1549,7 @@ rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, if (rte_intr_dev_fd_set(intr_handle, vfio_dev_fd)) return -rte_errno; - return 0; + return i; } /* if we're here, we haven't found a suitable interrupt vector */ @@ -1628,8 +1622,8 @@ fslmc_vfio_process_iodevices(struct rte_dpaa2_device *dev) switch (dev->dev_type) { case DPAA2_ETH: ret = rte_dpaa2_vfio_setup_intr(dev->intr_handle, dev_fd, - device_info.num_irqs); - if (ret) + device_info.num_irqs, VFIO_IRQ_INFO_EVENTFD); + if (ret < 0) return ret; break; case DPAA2_CON: diff --git a/drivers/bus/fslmc/fslmc_vfio.h b/drivers/bus/fslmc/fslmc_vfio.h index 34f2d7759c..9934bc0e86 100644 --- a/drivers/bus/fslmc/fslmc_vfio.h +++ b/drivers/bus/fslmc/fslmc_vfio.h @@ -45,8 +45,8 @@ int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index); __rte_internal int rte_dpaa2_intr_disable(struct rte_intr_handle *intr_handle, int index); -int rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, int vfio_dev_fd, - int num_irqs); +int rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle, + int vfio_dev_fd, int num_irqs, uint32_t flag); int fslmc_vfio_core_cluster_sdest(uint32_t cpu_id); diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index e95345627d..17af74aad8 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -66,6 +66,13 @@ static uint32_t io_space_count; /* Variable to hold the portal_key, once created.*/ static pthread_key_t dpaa2_portal_key; +struct dpaa2_dpio_gov_save { + char prev[32]; + uint8_t valid; +}; + +static struct dpaa2_dpio_gov_save s_dpaa2_dpio_gov_save[RTE_MAX_LCORE]; + static struct dpaa2_dpio_dev *get_dpio_dev_from_id(int32_t dpio_id) { struct dpaa2_dpio_dev *dpio_dev = NULL; @@ -105,59 +112,92 @@ dpaa2_get_core_id(void) return cpu_id; } -static void -dpaa2_affine_dpio_intr_to_respective_core(int32_t dpio_id, int cpu_id) +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_affinity_set) +int dpaa2_dpio_intr_affinity_set(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) { -#define STRING_LEN 28 -#define AFFINITY_LEN 128 - uint32_t cpu_mask = 1; - size_t len = 0; - char *temp = NULL, *token = NULL; - char string[STRING_LEN]; - char smp_affinity[AFFINITY_LEN]; - FILE *file; - - snprintf(string, STRING_LEN, "dpio.%d", dpio_id); - file = fopen("/proc/interrupts", "r"); - if (!file) { - DPAA2_BUS_WARN("Failed to open /proc/interrupts file"); - return; + char line[512], match[32], path[64]; + FILE *fp; + long irq = -1; + int32_t dpio_id = dpio_dev->hw_id, ret = 0; + +#define IRQ_ALL_F "/proc/interrupts" +#define IRQ_SMP_AFFINITY_F "/proc/irq/%ld/smp_affinity_list" + + if (cpu_id < 0 || cpu_id >= RTE_MAX_LCORE) + return -EINVAL; + + /* Token we look for on each /proc/interrupts line, e.g. "dpio.17". */ + snprintf(match, sizeof(match), "dpio.%d", dpio_id); + + fp = fopen(IRQ_ALL_F, "r"); + if (!fp) { + DPAA2_BUS_ERR("Failed to open %s: %s", IRQ_ALL_F, strerror(errno)); + return -errno; } - while (getline(&temp, &len, file) != -1) { - if ((strstr(temp, string)) != NULL) { - token = strtok(temp, ":"); - break; - } + + while (fgets(line, sizeof(line), fp)) { + char *p, next; + + /* + * Match the exact device token. Use the trailing '(' or ')' + * naming so that "dpio.17" does not accidentally match + * "dpio.170". We look for "dpio.<id>)" or "dpio.<id>(". + */ + p = strstr(line, match); + if (!p) + continue; + + /* Ensure the char right after the id is not another digit, + * so "dpio.17" won't match "dpio.170". + */ + next = p[strlen(match)]; + if (next >= '0' && next <= '9') + continue; + + /* IRQ number is the leading integer before the first ':'. */ + irq = strtol(line, NULL, 10); + break; } + fclose(fp); - if (!token) { - DPAA2_BUS_WARN("Failed to get interrupt id for dpio.%d", - dpio_id); - free(temp); - fclose(file); - return; + if (irq < 0) { + DPAA2_BUS_ERR("IRQ for dpio.%d not found in %s", dpio_id, IRQ_ALL_F); + return -ENOENT; + } + + /* + * Write the CPU as a decimal list to smp_affinity_list; this is the + * simplest and least error-prone form (no hex bitmask math needed). + * Equivalent to writing (1 << cpu_id) in hex to smp_affinity. + */ + snprintf(path, sizeof(path), IRQ_SMP_AFFINITY_F, irq); + + fp = fopen(path, "w"); + if (!fp) { + DPAA2_BUS_ERR("Failed to open %s: %s", path, strerror(errno)); + return -errno; } - cpu_mask = cpu_mask << cpu_id; - snprintf(smp_affinity, AFFINITY_LEN, "/proc/irq/%s/smp_affinity", token); - free(temp); - fclose(file); + if (fprintf(fp, "%d\n", cpu_id) < 0) { + DPAA2_BUS_ERR("Failed to write %s: %s", path, strerror(errno)); + ret = -EIO; + goto close_f; + } - file = fopen(smp_affinity, "w"); - if (file == NULL) { - DPAA2_BUS_WARN("Failed to open %s", smp_affinity); - return; + if (fflush(fp) != 0 || ferror(fp)) { + DPAA2_BUS_ERR("Error writing affinity to %s", path); + ret = -EIO; } - fprintf(file, "%X\n", cpu_mask); - fflush(file); - if (ferror(file)) { - fclose(file); - DPAA2_BUS_WARN("Failed to write to %s", smp_affinity); - return; +close_f: + fclose(fp); + + if (!ret) { + DPAA2_BUS_INFO("dpio.%d -> IRQ %ld affinity set to CPU %d", + dpio_id, irq, cpu_id); } - fclose(file); + return ret; } /* Pin the dpio's MSI IRQ to the calling lcore's core (best-effort), so a @@ -165,12 +205,104 @@ dpaa2_affine_dpio_intr_to_respective_core(int32_t dpio_id, int cpu_id) */ RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_affine_intr_to_core) void -dpaa2_dpio_affine_intr_to_core(int32_t dpio_id) +dpaa2_dpio_affine_intr_to_core(struct dpaa2_dpio_dev *dpio_dev) +{ + int cpu_id = dpaa2_get_core_id(), ret; + + if (cpu_id >= 0) { + ret = dpaa2_dpio_intr_affinity_set(dpio_dev, cpu_id); + if (ret) + DPAA2_BUS_ERR("Failed(%d) to affinity interrupt on core.%d", ret, cpu_id); + } +} + +static int _dpaa2_dpio_cpufreq_governor(uint32_t cpu_id, bool restore) +{ + struct dpaa2_dpio_gov_save *gov; + char path[64], prev[32]; + FILE *fp; + int ret = 0; + const char *str; + +#define CPU_FREQ_SCALING_GOVERNOR_F \ + "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor" + + if (cpu_id >= RTE_MAX_LCORE) + return -EINVAL; + + gov = &s_dpaa2_dpio_gov_save[cpu_id]; + if (!gov->valid && restore) + return 0; + + snprintf(path, sizeof(path), CPU_FREQ_SCALING_GOVERNOR_F, cpu_id); + if (restore) { + str = gov->prev; + goto set_governor; + } + + if (!gov->valid) { + fp = fopen(path, "r"); + if (!fp) { + DPAA2_BUS_ERR("Failed to open %s in r mode: %s", path, strerror(errno)); + return -errno; + } + if (fgets(prev, sizeof(prev), fp)) { + prev[strcspn(prev, "\n")] = '\0'; + snprintf(gov->prev, sizeof(gov->prev), "%s", prev); + } + fclose(fp); + } + str = "performance"; + +set_governor: + fp = fopen(path, "w"); + if (!fp) { + DPAA2_BUS_ERR("Failed to open %s in w mode: %s", path, strerror(errno)); + return -errno; + } + + if (fprintf(fp, "%s\n", str) < 0) { + DPAA2_BUS_ERR("Failed to write %s to %s: %s", str, path, strerror(errno)); + ret = -EIO; + goto close_f; + } + + if (fflush(fp)) { + DPAA2_BUS_ERR("Failed to flush %s: %s", path, strerror(errno)); + ret = -EIO; + } + +close_f: + fclose(fp); + + if (!ret) { + DPAA2_BUS_INFO("Set cpu%d's freq as performance mode.", cpu_id); + gov->valid = restore ? 0 : 1; + } + + return ret; +} + +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_cpufreq_governor) +int dpaa2_dpio_cpufreq_governor(int cpu_id, bool restore) { - int cpu_id = dpaa2_get_core_id(); + bool governor_all = cpu_id < 0 ? true : false; + int ret = 0; - if (cpu_id >= 0) - dpaa2_affine_dpio_intr_to_respective_core(dpio_id, cpu_id); + if (cpu_id >= RTE_MAX_LCORE) + return -EINVAL; + + if (governor_all) { + for (cpu_id = 0; cpu_id < RTE_MAX_LCORE; cpu_id++) { + ret = _dpaa2_dpio_cpufreq_governor(cpu_id, restore); + if (ret) + break; + } + } else { + ret = _dpaa2_dpio_cpufreq_governor(cpu_id, restore); + } + + return ret; } /* threshold: DQRR fill raising DQRI (< ring depth); timeout: holdoff in ITP units. @@ -183,13 +315,20 @@ RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_init) int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, int timeout, bool build_epoll) { - int eventfd, dpio_epoll_fd, ret; + int eventfd, dpio_epoll_fd, ret, index; struct rte_epoll_event *epoll_ev; if (dpio_dev->intr_enabled) return 0; - ret = rte_dpaa2_intr_enable(dpio_dev->intr_handle, 0); + index = rte_dpaa2_vfio_setup_intr(dpio_dev->intr_handle, dpio_dev->vfio_fd, + dpio_dev->num_irqs, VFIO_IRQ_INFO_EVENTFD); + if (index < 0) { + DPAA2_BUS_ERR("Fail(%d) to setup interrupt for %d", index, dpio_dev->hw_id); + return index; + } + + ret = rte_dpaa2_intr_enable(dpio_dev->intr_handle, index); if (ret) { DPAA2_BUS_ERR("Failed(%d) to enable dpio interrupt", ret); return ret; @@ -234,14 +373,15 @@ int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, } } - dpio_dev->intr_enabled = 1; + dpio_dev->intr_enabled = true; + dpio_dev->intr_index = index; return 0; epoll_close_err: close(dpio_epoll_fd); int_disable_err: - rte_dpaa2_intr_disable(dpio_dev->intr_handle, 0); + rte_dpaa2_intr_disable(dpio_dev->intr_handle, index); return ret; } @@ -265,15 +405,16 @@ void dpaa2_dpio_intr_deinit(struct dpaa2_dpio_dev *dpio_dev) close(epfd); } - ret = rte_dpaa2_intr_disable(dpio_dev->intr_handle, 0); + ret = rte_dpaa2_intr_disable(dpio_dev->intr_handle, dpio_dev->intr_index); if (ret) DPAA2_BUS_ERR("DPIO interrupt disable failed(%d)", ret); - dpio_dev->intr_enabled = 0; + dpio_dev->intr_enabled = false; } -static int -dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_configure_stashing) +int +dpaa2_dpio_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) { int sdest, ret; @@ -281,19 +422,18 @@ dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) * Valid values of SDEST are 4,5,6,7. Where, */ sdest = fslmc_vfio_core_cluster_sdest(cpu_id); - DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", - dpio_dev->index, cpu_id, sdest); + DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", dpio_dev->index, cpu_id, sdest); if (sdest < 0) return sdest; ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, - dpio_dev->token, sdest); + dpio_dev->token, sdest); if (ret) { - DPAA2_BUS_ERR("%d ERROR in SDEST", ret); - return ret; + DPAA2_BUS_ERR("Failed(%d) to set stashing(%02x) of dpio.%d/cpu.%d", + ret, sdest, dpio_dev->hw_id, cpu_id); } - return 0; + return ret; } static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) @@ -335,9 +475,9 @@ static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(bool ethrx) if (dpaa2_svr_family != SVR_LX2160A) qbman_swp_update(dpio_dev->sw_portal, 1); } else { - ret = dpaa2_configure_stashing(dpio_dev, cpu_id); + ret = dpaa2_dpio_configure_stashing(dpio_dev, cpu_id); if (ret) { - DPAA2_BUS_ERR("dpaa2_configure_stashing failed"); + DPAA2_BUS_ERR("Failed(%d) to configure stashing", ret); rte_atomic_store_explicit(&dpio_dev->ref_count, 0, rte_memory_order_release); return NULL; @@ -453,7 +593,7 @@ rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, int32_t cpu_affine) return NULL; } if (cpu_affine >= 0) - dpaa2_affine_dpio_intr_to_respective_core(dpio_dev->hw_id, cpu_affine); + dpaa2_dpio_intr_affinity_set(dpio_dev, cpu_affine); quit: #else RTE_SET_USED(isr); @@ -533,18 +673,13 @@ dpaa2_create_dpio_device(int vdev_fd, dpio_dev->dpio = NULL; dpio_dev->hw_id = object_id; + dpio_dev->vfio_fd = vdev_fd; + dpio_dev->intr_handle = obj->intr_handle; + dpio_dev->num_irqs = obj_info->num_irqs; rte_atomic_store_explicit(&dpio_dev->ref_count, 0, rte_memory_order_relaxed); /* Using single portal for all devices */ dpio_dev->mc_portal = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX); - /* Allocate interrupt instance */ - dpio_dev->intr_handle = - rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED); - if (!dpio_dev->intr_handle) { - DPAA2_BUS_ERR("Failed to allocate intr handle"); - goto err; - } - dpio_dev->dpio = rte_zmalloc(NULL, sizeof(struct fsl_mc_io), RTE_CACHE_LINE_SIZE); if (!dpio_dev->dpio) { @@ -553,8 +688,7 @@ dpaa2_create_dpio_device(int vdev_fd, } dpio_dev->dpio->regs = dpio_dev->mc_portal; - if (dpio_open(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->hw_id, - &dpio_dev->token)) { + if (dpio_open(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->hw_id, &dpio_dev->token)) { DPAA2_BUS_ERR("Failed to allocate IO space"); goto err; } @@ -569,8 +703,7 @@ dpaa2_create_dpio_device(int vdev_fd, goto err; } - if (dpio_get_attributes(dpio_dev->dpio, CMD_PRI_LOW, - dpio_dev->token, &attr)) { + if (dpio_get_attributes(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token, &attr)) { DPAA2_BUS_ERR("DPIO Get attribute failed"); goto err; } @@ -587,8 +720,7 @@ dpaa2_create_dpio_device(int vdev_fd, dpio_dev->ce_size = reg_info.size; dpio_dev->qbman_portal_ce_paddr = (size_t)mmap(NULL, reg_info.size, - PROT_WRITE | PROT_READ, MAP_SHARED, - vdev_fd, reg_info.offset); + PROT_WRITE | PROT_READ, MAP_SHARED, vdev_fd, reg_info.offset); reg_info.index = DPAA2_SWP_CINH_REGION; if (ioctl(vdev_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) { @@ -598,8 +730,7 @@ dpaa2_create_dpio_device(int vdev_fd, dpio_dev->ci_size = reg_info.size; dpio_dev->qbman_portal_ci_paddr = (size_t)mmap(NULL, reg_info.size, - PROT_WRITE | PROT_READ, MAP_SHARED, - vdev_fd, reg_info.offset); + PROT_WRITE | PROT_READ, MAP_SHARED, vdev_fd, reg_info.offset); /* Configure & setup SW portal */ p_des.block = NULL; @@ -620,12 +751,6 @@ dpaa2_create_dpio_device(int vdev_fd, io_space_count++; dpio_dev->index = io_space_count; - if (rte_dpaa2_vfio_setup_intr(dpio_dev->intr_handle, vdev_fd, 1)) { - DPAA2_BUS_ERR("Fail to setup interrupt for %d", - dpio_dev->hw_id); - goto err; - } - dpio_dev->eqresp = rte_zmalloc(NULL, MAX_EQ_RESP_ENTRIES * (sizeof(struct qbman_result) + sizeof(struct eqresp_metadata)), @@ -668,7 +793,6 @@ dpaa2_create_dpio_device(int vdev_fd, rte_free(dpio_dev->dpio); } - rte_intr_instance_free(dpio_dev->intr_handle); rte_free(dpio_dev); /* For each element in the list, cleanup */ @@ -680,7 +804,6 @@ dpaa2_create_dpio_device(int vdev_fd, dpio_dev->token); rte_free(dpio_dev->dpio); } - rte_intr_instance_free(dpio_dev->intr_handle); rte_free(dpio_dev); } diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 0d0894572a..7c089408c5 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -38,6 +38,15 @@ RTE_DECLARE_PER_LCORE(struct dpaa2_io_portal_t, _dpaa2_io); #define DPAA2_PER_LCORE_DQRR_MBUF(i) \ RTE_PER_LCORE(_dpaa2_io).dpio_dev->dpaa2_held_bufs.mbuf[i] +__rte_internal int +dpaa2_dpio_intr_affinity_set(struct dpaa2_dpio_dev *dpio_dev, int cpu_id); + +__rte_internal int +dpaa2_dpio_cpufreq_governor(int cpu_id, bool restore); + +__rte_internal int +dpaa2_dpio_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id); + /* Affine a DPIO portal to current processing thread */ __rte_internal int dpaa2_affine_qbman_swp(void); @@ -56,7 +65,7 @@ void dpaa2_dpio_intr_deinit(struct dpaa2_dpio_dev *dpio_dev); /* pin a DPIO's MSI IRQ to the calling lcore's core (rx-queue interrupt mode) */ __rte_internal -void dpaa2_dpio_affine_intr_to_core(int32_t dpio_id); +void dpaa2_dpio_affine_intr_to_core(struct dpaa2_dpio_dev *dpio_dev); /* allocate memory for FQ - dq storage */ __rte_internal diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 52ec660fb9..95c7203aa2 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -133,6 +133,9 @@ struct dpaa2_dpio_dev { /**< Physical address of Cache Inhibit Area */ uintptr_t ci_size; /**< Size of the CI region */ struct rte_intr_handle *intr_handle; /* Interrupt related info */ + int32_t vfio_fd; + uint32_t num_irqs; + int32_t intr_index; int32_t hw_id; /**< An unique ID of this DPIO device instance */ uint8_t intr_enabled; /**< DQRI portal interrupt already set up */ int32_t cpu_affine; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index f4dbf47b18..ad80fd51f5 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -88,6 +88,7 @@ static __rte_always_inline struct dpaa2_dpio_dev * dpaa2_event_portal_io_prepare(struct dpaa2_port *dpaa2_portal) { struct dpaa2_dpio_dev *dpio_dev; + int ret, cpu = rte_lcore_id(); if (unlikely(!dpaa2_portal->dpio_dev)) { DPAA2_EVENTDEV_ERR("Event port%d not setup", dpaa2_portal->port_id); @@ -106,10 +107,23 @@ dpaa2_event_portal_io_prepare(struct dpaa2_port *dpaa2_portal) if (unlikely(!dpaa2_portal->port_atomic && !rte_atomic_load_explicit(&dpaa2_portal->flushing, rte_memory_order_relaxed)) && - dpio_dev->cpu_affine != (int32_t)rte_lcore_id()) { + dpio_dev->cpu_affine != cpu) { DPAA2_EVENTDEV_DEBUG("Event port%d affine CPU from %d->%d", - dpaa2_portal->port_id, dpio_dev->cpu_affine, rte_lcore_id()); - dpio_dev->cpu_affine = rte_lcore_id(); + dpaa2_portal->port_id, dpio_dev->cpu_affine, cpu); + dpio_dev->cpu_affine = cpu; + ret = dpaa2_dpio_intr_affinity_set(dpio_dev, cpu); + if (ret) { + DPAA2_EVENTDEV_ERR("Failed(%d) to affinity dpio.%d's interrupt on core%d", + ret, dpio_dev->hw_id, cpu); + } + ret = dpaa2_dpio_cpufreq_governor(cpu, false); + if (ret) + DPAA2_EVENTDEV_WARN("Failed(%d) to set governor of core%d", ret, cpu); + ret = dpaa2_dpio_configure_stashing(dpio_dev, cpu); + if (ret) { + DPAA2_EVENTDEV_WARN("Failed(%d) to configure dpio.%d's stashing on core%d", + ret, dpio_dev->hw_id, cpu); + } } return dpio_dev; @@ -588,6 +602,15 @@ dpaa2_eventdev_close(struct rte_eventdev *dev) dpaa2_eventdev_port_release(dev->data->ports[i]); } + /* + * Restore any CPU-frequency governor that the optional first-touch + * binding may have forced (see dpaa2_dpio_cpufreq_governor(cpu, false)). + * Best-effort and a no-op when the governor was never touched. + */ + ret = dpaa2_dpio_cpufreq_governor(-1, true); + if (ret) + DPAA2_EVENTDEV_ERR("Failed(%d) to restore all cpus' governors", ret); + ret = dpaa2_eventdev_eth_queue_del(dev, NULL, -1); if (!ret) priv->status = DPAA2_EVENTDEV_CREATED; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c1a0ae7763..88a0f9bdbb 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3669,7 +3669,7 @@ dpaa2_napi_subscribe(struct rte_eth_dev *dev, uint16_t queue_id, /* pin this portal's MSI to the worker's core: a CDAN wake then lands on * the same core the worker sleeps on, instead of the default spread. */ - dpaa2_dpio_affine_intr_to_core(dpio->hw_id); + dpaa2_dpio_affine_intr_to_core(dpio); return 0; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 48/65] bus/fslmc: move Tx SG mempool to fslmc bus 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (46 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 47/65] bus/fslmc: defer DPIO interrupt setup and bind portal to worker core Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 49/65] net/dpaa2: move DPNI endpoint lookup out of the " Prashant Gupta ` (16 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The scatter-gather mbuf pool used to build multi-segment Tx frames was a global owned by the dpaa2 net PMD (dpaa2_tx_sg_pool), created lazily on first probe and reference-counted with dpaa2_valid_dev. This tied a bus-wide resource to the net driver and duplicated primary/secondary lookup logic. Create the SG pool once on the fslmc bus instead: - Allocate "dpaa2_sg_pool" in rte_fslmc_probe() and free it in rte_fslmc_close(), storing the handle in fslmc_bus_info.mem_pool. - Expose the pool sizing via DPAA2_TX_SG_POOL_SIZE, DPAA2_TX_SG_POOL_CACHE_SIZE and DPAA2_TX_SG_POOL_ELEM_SIZE in the bus driver header. Update the net PMD to consume it: - dpaa2_dev_init() takes the pool from the device's bus_info and stores it in priv->tx_sg_pool; dpaa2_dev_close() clears the reference. - Remove dpaa2_tx_sg_pool_init(), the dpaa2_tx_sg_pool / dpaa2_valid_dev globals, and the now-unused DPAA2_MAX_SGS, DPAA2_POOL_SIZE, DPAA2_POOL_CACHE_SIZE and struct sw_buf_free definitions. - Bound the SG receive walk by the pool element size instead of DPAA2_MAX_SGS. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 4 +++ drivers/bus/fslmc/fslmc_bus.c | 9 ++++++ drivers/net/dpaa2/dpaa2_ethdev.c | 44 ++-------------------------- drivers/net/dpaa2/dpaa2_ethdev.h | 20 ++----------- drivers/net/dpaa2/dpaa2_rxtx.c | 9 +++--- 5 files changed, 22 insertions(+), 64 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 3ba865e632..4d56da45b3 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -89,6 +89,10 @@ enum rte_dpaa2_dev_type { DPAA2_DEVTYPE_MAX, }; +#define DPAA2_TX_SG_POOL_SIZE 2048 +#define DPAA2_TX_SG_POOL_CACHE_SIZE 256 +#define DPAA2_TX_SG_POOL_ELEM_SIZE 2048 + struct rte_fslmc_bus_info { void *mem_pool; int sp_protocol; diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index a418f9a420..d20103ee36 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -690,6 +690,10 @@ rte_fslmc_probe(struct rte_bus *bus) return ret; } + fslmc_bus_info.mem_pool = rte_pktmbuf_pool_create("dpaa2_sg_pool", + DPAA2_TX_SG_POOL_SIZE, DPAA2_TX_SG_POOL_CACHE_SIZE, 0, + DPAA2_TX_SG_POOL_ELEM_SIZE, rte_socket_id()); + return rte_bus_generic_probe(bus); } @@ -750,6 +754,11 @@ rte_fslmc_close(struct rte_bus *bus __rte_unused) { int ret = 0; + if (fslmc_bus_info.mem_pool) { + rte_mempool_free(fslmc_bus_info.mem_pool); + fslmc_bus_info.mem_pool = NULL; + } + ret = fslmc_bus_close_group(); if (ret) DPAA2_BUS_INFO("Unable to close devices %d", ret); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 88a0f9bdbb..995e0db1f2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -203,9 +203,6 @@ dpaa2_dist_size_is_supported(uint16_t n) return false; } -int dpaa2_valid_dev; -struct rte_mempool *dpaa2_tx_sg_pool; - struct dpaa2_xstats_seq { struct dpni_statistics_page_0 pg0; struct dpni_statistics_page_1 pg1; @@ -2402,6 +2399,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) /* Free the allocated memory for ethernet private data and dpni*/ priv->hw = NULL; + priv->tx_sg_pool = NULL; dev->process_private = NULL; rte_free(dpni); @@ -4195,6 +4193,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) eth_dev->data->name, dpaa2_dev->ep_name); priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); + priv->tx_sg_pool = dpaa2_dev->bus_info->mem_pool; return 0; init_err: @@ -4244,35 +4243,6 @@ rte_pmd_dpaa2_ep_name(uint32_t eth_id) return priv->ep_name; } -static int dpaa2_tx_sg_pool_init(void) -{ - char name[RTE_MEMZONE_NAMESIZE]; - - if (dpaa2_tx_sg_pool) - return 0; - - sprintf(name, "dpaa2_mbuf_tx_sg_pool"); - if (rte_eal_process_type() == RTE_PROC_PRIMARY) { - dpaa2_tx_sg_pool = rte_pktmbuf_pool_create(name, - DPAA2_POOL_SIZE, - DPAA2_POOL_CACHE_SIZE, 0, - DPAA2_MAX_SGS * sizeof(struct qbman_sge), - rte_socket_id()); - if (!dpaa2_tx_sg_pool) { - DPAA2_PMD_ERR("SG pool creation failed"); - return -ENOMEM; - } - } else { - dpaa2_tx_sg_pool = rte_mempool_lookup(name); - if (!dpaa2_tx_sg_pool) { - DPAA2_PMD_ERR("SG pool lookup failed"); - return -ENOMEM; - } - } - - return 0; -} - static int rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv, struct rte_dpaa2_device *dpaa2_dev) @@ -4326,11 +4296,7 @@ rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv, /* Invoke PMD device initialization function */ diag = dpaa2_dev_init(eth_dev); if (!diag) { - diag = dpaa2_tx_sg_pool_init(); - if (diag) - return diag; rte_eth_dev_probing_finish(eth_dev); - dpaa2_valid_dev++; return 0; } @@ -4353,12 +4319,6 @@ rte_dpaa2_remove(struct rte_dpaa2_device *dpaa2_dev) ret = rte_eth_dev_release_port(eth_dev); } - dpaa2_valid_dev--; - if (!dpaa2_valid_dev) { - rte_mempool_free(dpaa2_tx_sg_pool); - dpaa2_tx_sg_pool = NULL; - } - return ret; } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e4dc7b7e4f..91414114ac 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -223,24 +223,6 @@ #define DPAA2_MAC_STATS_INDEX_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint32_t)) #define DPAA2_MAC_STATS_VALUE_DMA_SIZE (DPAA2_MAC_NUM_STATS * sizeof(uint64_t)) -/* Global pool used by driver for SG list TX */ -extern struct rte_mempool *dpaa2_tx_sg_pool; -/* Maximum SG segments */ -#define DPAA2_MAX_SGS 128 -/* SG pool size */ -#define DPAA2_POOL_SIZE 2048 -/* SG pool cache size */ -#define DPAA2_POOL_CACHE_SIZE 256 -/* structure to free external and indirect - * buffers. - */ -struct sw_buf_free { - /* To which packet this segment belongs */ - uint16_t pkt_id; - /* The actual segment */ - struct rte_mbuf *seg; -}; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; @@ -478,6 +460,8 @@ struct dpaa2_dev_priv { */ union dpni_statistics pg_xstats[DPNI_MAX_STATISTICS_PAGE_ID][DPNI_STAT_MAX_PARAM]; + struct rte_mempool *tx_sg_pool; + LIST_HEAD(, dpaa2_dev_flow) flows; LIST_HEAD(, dpaa2_dev_meter_profile) profiles; LIST_HEAD(, dpaa2_dev_meter_policy) policies; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index a44b991d1b..6d12e6818d 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -456,7 +456,7 @@ dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) (void **)&first_seg, 1, 1); #endif cur_seg = first_seg; - while (!DPAA2_SG_IS_FINAL(sge) && i < DPAA2_MAX_SGS) { + while (!DPAA2_SG_IS_FINAL(sge)) { sge = &sgt[i++]; sg_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FLE_ADDR(sge)); next_seg = DPAA2_INLINE_MBUF_FROM_BUF(sg_addr, @@ -746,6 +746,7 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, uint16_t nb_segs = mbuf->nb_segs; uint32_t sg_size = nb_segs * sizeof(struct qbman_sge); struct rte_mempool *mp; + struct dpaa2_dev_priv *priv = txq->eth_data->dev_private; if (conf == DPAA2_TX_DYNAMIC_CONF) { while (cur_seg) { @@ -789,8 +790,8 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, DPAA2_SET_FD_OFFSET(fd, offset); } else { sg_mbuf = NULL; - if (dpaa2_tx_sg_pool) - sg_mbuf = rte_pktmbuf_alloc(dpaa2_tx_sg_pool); + if (priv->tx_sg_pool) + sg_mbuf = rte_pktmbuf_alloc(priv->tx_sg_pool); if (!sg_mbuf) { DPAA2_PMD_DP_DEBUG("No memory to allocate S/G table"); return -ENOMEM; @@ -803,7 +804,7 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, DPAA2_SET_ONLY_FD_BPID(fd, MAX_BPID); DPAA2_SET_FD_IVP(fd); } else { - DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(dpaa2_tx_sg_pool)); + DPAA2_SET_ONLY_FD_BPID(fd, mempool_to_bpid(priv->tx_sg_pool)); } DPAA2_SET_FD_OFFSET(fd, sg_mbuf->data_off); offset = sg_mbuf->data_off; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 49/65] net/dpaa2: move DPNI endpoint lookup out of the fslmc bus 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (47 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 48/65] bus/fslmc: move Tx SG mempool to fslmc bus Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 50/65] net/dpaa2: add APIs to query device info and set default action Prashant Gupta ` (15 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The fslmc bus scan was doing a DPNI-specific endpoint lookup for every DPAA2 device inside rte_dpaa2_create_dprc_device(): for each DPAA2_ETH object it issued dprc_get_connection(dpni.<id>) and stored the result (ep_dev_type / ep_object_id / ep_name) directly on the generic rte_dpaa2_device. This had several problems: - It made the generic bus device carry DPNI-specific knowledge. Non-eth DPAA2 object types (DPCI, DPIO, DPSECI, DPDMAI, ...) that may also have endpoints never populated these fields, so the "endpoint" of any non-DPNI device was silently wrong. - DPDMUX and DPSW endpoints are per-interface (identified by endpoint.if_id in addition to the object id), but the bus code only ever formatted "<type>.<id>" and dropped if_id, producing an ambiguous ep_name for those connection types. - A dprc_get_connection() failure on any single DPNI aborted the whole DPRC scan and freed the dprc node, even if the failing DPNI was never going to be used by this process. - It coupled the bus scan to the MC command set exposed by fsl_dprc.h, and forced every DPAA2 user of the bus to carry those symbols even if it did not care about endpoints. Move the DPNI endpoint lookup where it belongs: into the DPAA2 net PMD, which is the only consumer today. The bus layer now just assigns each device to its parent DPRC container during the scan and lets each object driver decide whether (and how) to resolve its endpoint. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 3 -- drivers/bus/fslmc/portal/dpaa2_hw_dprc.c | 49 +++----------------- drivers/net/dpaa2/dpaa2_ethdev.c | 59 +++++++++++++++++++++++- drivers/net/dpaa2/dpaa2_recycle.c | 15 +++--- 4 files changed, 71 insertions(+), 55 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 4d56da45b3..40c9ba0699 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -108,10 +108,7 @@ struct rte_dpaa2_device { struct rte_device device; /**< Inherit core device */ enum rte_dpaa2_dev_type dev_type; /**< Device Type */ uint16_t object_id; /**< DPAA2 Object ID */ - enum rte_dpaa2_dev_type ep_dev_type; /**< Endpoint Device Type */ struct dpaa2_dprc_dev *container; - uint16_t ep_object_id; /**< Endpoint DPAA2 Object ID */ - char ep_name[RTE_DEV_NAME_MAX_LEN]; struct rte_intr_handle *intr_handle; /**< Interrupt handle */ char name[FSLMC_OBJECT_MAX_LEN]; /**< DPAA2 Object name*/ const struct rte_fslmc_bus_info *bus_info; diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c index 2234da0975..92238c174e 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dprc.c @@ -28,7 +28,6 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, struct rte_dpaa2_device *obj) { struct dpaa2_dprc_dev *dprc_node; - struct dprc_endpoint endpoint1, endpoint2; struct rte_dpaa2_device *dev; int ret, dprc_id = obj->object_id; @@ -50,50 +49,14 @@ rte_dpaa2_create_dprc_device(int vdev_fd __rte_unused, return ret; } - RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) { - /** DPRC is always created before it's children are created.*/ + /* DPRC is always created before its children are created, so every + * device scanned so far belongs to this container. Endpoint lookup is + * left to the object drivers, which know how many interfaces their + * object has and can report a failure to their own caller. + */ + RTE_BUS_FOREACH_DEV(dev, &rte_fslmc_bus) dev->container = dprc_node; - if (rte_bus_device_is_ignored(&rte_fslmc_bus, dev->device.name)) - continue; - - if (dev->dev_type == DPAA2_ETH) { - int link_state; - - memset(&endpoint1, 0, sizeof(struct dprc_endpoint)); - memset(&endpoint2, 0, sizeof(struct dprc_endpoint)); - strcpy(endpoint1.type, "dpni"); - endpoint1.id = dev->object_id; - ret = dprc_get_connection(&dprc_node->dprc, - CMD_PRI_LOW, - dprc_node->token, - &endpoint1, &endpoint2, - &link_state); - if (ret) { - DPAA2_BUS_ERR("dpni.%d connection failed!", - dev->object_id); - dprc_close(&dprc_node->dprc, CMD_PRI_LOW, - dprc_node->token); - rte_free(dprc_node); - return ret; - } - - if (!strcmp(endpoint2.type, "dpmac")) - dev->ep_dev_type = DPAA2_MAC; - else if (!strcmp(endpoint2.type, "dpni")) - dev->ep_dev_type = DPAA2_ETH; - else if (!strcmp(endpoint2.type, "dpdmux")) - dev->ep_dev_type = DPAA2_MUX; - else - dev->ep_dev_type = DPAA2_UNKNOWN; - - dev->ep_object_id = endpoint2.id; - } else { - dev->ep_dev_type = DPAA2_UNKNOWN; - } - sprintf(dev->ep_name, "%s.%d", endpoint2.type, endpoint2.id); - } - TAILQ_INSERT_TAIL(&dprc_dev_list, dprc_node, next); return 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 995e0db1f2..572fcca91a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -26,6 +26,7 @@ #include <dpaa2_hw_pvt.h> #include <dpaa2_hw_mempool.h> #include <dpaa2_hw_dpio.h> +#include <fsl_dprc.h> #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" @@ -3919,6 +3920,55 @@ populate_mac_addr(struct fsl_mc_io *dpni_dev, return ret; } +/* Resolve the object this DPNI is wired to inside its DPRC container. The + * endpoint decides whether MAC-level operations (link, promisc, flow control) + * are available, and it is reported to the application by + * rte_pmd_dpaa2_ep_name(). + */ +static int +dpaa2_dev_ep_init(struct rte_dpaa2_device *dpaa2_dev, + struct dpaa2_dev_priv *priv) +{ + struct dpaa2_dprc_dev *dprc_node = dpaa2_dev->container; + struct dprc_endpoint endpoint1, endpoint2; + int link_state, ret; + + memset(&endpoint1, 0, sizeof(endpoint1)); + memset(&endpoint2, 0, sizeof(endpoint2)); + strlcpy(endpoint1.type, "dpni", sizeof(endpoint1.type)); + endpoint1.id = dpaa2_dev->object_id; + ret = dprc_get_connection(&dprc_node->dprc, CMD_PRI_LOW, + dprc_node->token, &endpoint1, &endpoint2, &link_state); + if (ret) + return ret; + + if (strcmp(endpoint2.type, "dpmac") == 0) + priv->ep_dev_type = DPAA2_MAC; + else if (strcmp(endpoint2.type, "dpni") == 0) + priv->ep_dev_type = DPAA2_ETH; + else if (strcmp(endpoint2.type, "dpdmux") == 0) + priv->ep_dev_type = DPAA2_MUX; + else if (strcmp(endpoint2.type, "dpsw") == 0) + priv->ep_dev_type = DPAA2_SW; + else + priv->ep_dev_type = DPAA2_UNKNOWN; + + priv->ep_object_id = endpoint2.id; + + /* dpdmux and dpsw endpoints are per-interface, so the interface index + * is part of the name. + */ + if (priv->ep_dev_type == DPAA2_MUX || priv->ep_dev_type == DPAA2_SW) { + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d.%d", + endpoint2.type, endpoint2.id, endpoint2.if_id); + } else { + snprintf(priv->ep_name, sizeof(priv->ep_name), "%s.%d", + endpoint2.type, endpoint2.id); + } + + return 0; +} + static int dpaa2_dev_init(struct rte_eth_dev *eth_dev) { @@ -3991,6 +4041,13 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + ret = dpaa2_dev_ep_init(dpaa2_dev, priv); + if (ret) { + DPAA2_PMD_ERR("Failure in get dpni@%d endpoint, err code %d", + hw_id, ret); + goto init_err; + } + ret = dpni_get_api_version(dpni_dev, CMD_PRI_LOW, &priv->dpni_ver_major, &priv->dpni_ver_minor); if (ret) { @@ -4190,7 +4247,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->sp_protocol = dpaa2_dev->bus_info->sp_protocol; DPAA2_PMD_INFO("%s: netdev created, connected to %s", - eth_dev->data->name, dpaa2_dev->ep_name); + eth_dev->data->name, priv->ep_name); priv->speed_capa = dpaa2_dev_get_speed_capability(eth_dev); priv->tx_sg_pool = dpaa2_dev->bus_info->mem_pool; diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 48b531d847..4a693cfe04 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -626,18 +626,18 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_MAC) { + if (priv->ep_dev_type == DPAA2_MAC) { /** For dpmac-dpni connection, * try setting serdes loopback as recycle device at first. */ if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 1); if (!ret) { priv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE; return 0; @@ -666,8 +666,8 @@ dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev) return 0; } - if (dpaa2_dev->ep_dev_type == DPAA2_ETH && - dpaa2_dev->object_id == dpaa2_dev->ep_object_id) { + if (priv->ep_dev_type == DPAA2_ETH && + dpaa2_dev->object_id == priv->ep_object_id) { priv->flags |= DPAA2_TX_DPNI_LOOPBACK_MODE; return 0; @@ -680,7 +680,6 @@ int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) { struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; - struct rte_dpaa2_device *dpaa2_dev = RTE_CLASS_TO_BUS_DEVICE(eth_dev, *dpaa2_dev); struct fsl_mc_io *dpni_dev = eth_dev->process_private; struct dpni_port_cfg port_cfg; int ret = 0; @@ -690,7 +689,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) if (priv->flags & DPAA2_TX_SERDES_LOOPBACK_MODE) { if (dpaa2_svr_family == SVR_LS2088A) { - ret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = ls_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); @@ -698,7 +697,7 @@ dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev) priv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE; } } else if (dpaa2_svr_family == SVR_LX2160A) { - ret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0); + ret = lx_serdes_eth_lpbk(priv->ep_object_id, 0); if (ret) { DPAA2_PMD_WARN("Error(%d) to disable Serdes loopback", ret); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 50/65] net/dpaa2: add APIs to query device info and set default action 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (48 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 49/65] net/dpaa2: move DPNI endpoint lookup out of the " Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 51/65] net/dpaa2: consolidate dequeue paths and optimize fast path Prashant Gupta ` (14 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Add experimental dpaa2 PMD APIs so applications can discover the device's classification resources and program the default (table-miss) action for the QoS and flow-steering tables. - rte_pmd_dpaa2_dev_info_get(): return the generic rte_eth_dev_info plus dpaa2-specific resource counts (rx_tc_num, tx_tc_num, qos_entries, fs_entries, dist_queues) via struct rte_pmd_dpaa2_dev_info. - rte_pmd_dpaa2_rx_queue_info_get(): return the generic rte_eth_rxq_info plus the queue's tc_id and flow_id via struct rte_pmd_dpaa2_rxq_info, so applications can map a queue to its TC/flow. - rte_pmd_dpaa2_dev_configure_default_action(): set the per-TC default flow (or drop) for the FS tables and the default TC (or drop) for the QoS table via struct rte_pmd_dpaa2_default_action_conf, re-applying the table miss action for each affected table. New symbols are exported as experimental. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 104 ++++++++++++++++++++++++++++++ drivers/net/dpaa2/rte_pmd_dpaa2.h | 36 +++++++++++ 2 files changed, 140 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 572fcca91a..f00f906040 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1236,6 +1236,61 @@ dpaa2_dev_dcb_info(struct rte_eth_dev *dev, return 0; } +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_dev_configure_default_action, 26.11) +int +rte_pmd_dpaa2_dev_configure_default_action(uint16_t port_id, + struct rte_pmd_dpaa2_default_action_conf *def_act_conf) +{ + int ret; + struct rte_eth_dev *dev; + struct dpaa2_dev_priv *priv; + struct dpaa2_flow_tbl_profile *tbl_profile; + uint16_t base, tc_index, default_flow; + + if (!rte_pmd_dpaa2_dev_is_dpaa2(port_id)) + return -EINVAL; + + dev = &rte_eth_devices[port_id]; + priv = dev->data->dev_private; + + for (tc_index = 0; tc_index < priv->num_rx_tc; tc_index++) { + tbl_profile = &priv->flow_profile.tc_profile[tc_index]; + base = priv->dist_queues * tc_index; + if (tc_index >= def_act_conf->max_tc) + break; + default_flow = def_act_conf->default_flows[tc_index]; + if (default_flow >= priv->dist_queues) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_queue.index = base + default_flow; + } + if (priv->fs_entries) { + ret = dpaa2_setup_table_miss_action(dev, tc_index); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-tc%d table", + ret, dev->data->name, tc_index); + return ret; + } + } + } + + tbl_profile = &priv->flow_profile.qos_profile; + if (def_act_conf->default_tc >= priv->num_rx_tc) { + tbl_profile->default_drop = true; + } else { + tbl_profile->default_drop = false; + tbl_profile->default_jump.group = def_act_conf->default_tc; + } + ret = dpaa2_setup_table_miss_action(dev, priv->num_rx_tc); + if (ret) { + DPAA2_PMD_ERR("Error(%d) to set miss action of %s-QoS table", + ret, dev->data->name); + } + + return ret; +} + static int dpaa2_eth_dev_configure(struct rte_eth_dev *dev) { @@ -4300,6 +4355,55 @@ rte_pmd_dpaa2_ep_name(uint32_t eth_id) return priv->ep_name; } +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_rx_queue_info_get, 25.11) +int +rte_pmd_dpaa2_rx_queue_info_get(uint16_t port_id, uint16_t queue_id, + struct rte_pmd_dpaa2_rxq_info *qinfo) +{ + int ret; + struct rte_eth_dev *dev; + struct dpaa2_queue *rxq; + + if (!rte_pmd_dpaa2_dev_is_dpaa2(port_id)) + return -EINVAL; + + ret = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo->rxq_info); + if (ret) + return ret; + dev = &rte_eth_devices[port_id]; + rxq = dev->data->rx_queues[queue_id]; + qinfo->tc_id = rxq->tc_index; + qinfo->flow_id = rxq->flow_id; + + return 0; +} + +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_dev_info_get, 25.11) +int +rte_pmd_dpaa2_dev_info_get(uint16_t port_id, + struct rte_pmd_dpaa2_dev_info *dev_info) +{ + int ret; + struct rte_eth_dev *dev; + struct dpaa2_dev_priv *priv; + + if (!rte_pmd_dpaa2_dev_is_dpaa2(port_id)) + return -EINVAL; + + ret = rte_eth_dev_info_get(port_id, &dev_info->dev_info); + if (ret) + return ret; + dev = &rte_eth_devices[port_id]; + priv = dev->data->dev_private; + dev_info->rx_tc_num = priv->num_rx_tc; + dev_info->tx_tc_num = priv->num_tx_tc; + dev_info->qos_entries = priv->qos_entries; + dev_info->fs_entries = priv->fs_entries; + dev_info->dist_queues = priv->dist_queues; + + return 0; +} + static int rte_dpaa2_probe(struct rte_dpaa2_driver *dpaa2_drv, struct rte_dpaa2_device *dpaa2_dev) diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index 74b7e63c54..5a61a952bf 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -167,6 +167,42 @@ uint16_t rte_dpaa2_dev_tx_multi_ports(uint16_t port_id[], uint16_t txq_id[], struct rte_mbuf **bufs, uint16_t nb_pkts); +struct rte_pmd_dpaa2_rxq_info { + struct rte_eth_rxq_info rxq_info; + uint8_t tc_id; + uint16_t flow_id; +}; + +__rte_experimental +int +rte_pmd_dpaa2_rx_queue_info_get(uint16_t port_id, uint16_t queue_id, + struct rte_pmd_dpaa2_rxq_info *qinfo); + +struct rte_pmd_dpaa2_dev_info { + struct rte_eth_dev_info dev_info; + uint8_t rx_tc_num; + uint8_t tx_tc_num; + uint16_t qos_entries; + uint16_t fs_entries; + uint16_t dist_queues; +}; + +__rte_experimental +int +rte_pmd_dpaa2_dev_info_get(uint16_t port_id, + struct rte_pmd_dpaa2_dev_info *dev_info); + +struct rte_pmd_dpaa2_default_action_conf { + uint8_t default_tc; + uint8_t max_tc; + uint16_t default_flows[]; +}; + +__rte_experimental +int +rte_pmd_dpaa2_dev_configure_default_action(uint16_t port_id, + struct rte_pmd_dpaa2_default_action_conf *def_act_conf); + #define RTE_DPAA2_EVENT_PORT_CFG_ATOMIC RTE_BIT32(31) /** RTE_DPAA2_MIX_GROUP_FLOW has same behavio as RTE_DPAA2_FLAT_GROUP_FLOW*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 51/65] net/dpaa2: consolidate dequeue paths and optimize fast path 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (49 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 50/65] net/dpaa2: add APIs to query device info and set default action Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 52/65] net/dpaa2: bind per-queue DPIO for rx-queue interrupts Prashant Gupta ` (13 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Unify the many duplicated QBMAN volatile-dequeue (VDQ) implementations in the dpaa2 PMD behind shared helpers and route every Rx-side path through a single prefetch/dequeue core, cutting duplicated code and trimming the per-packet work on the common forwarding configuration. Shared dequeue helpers: - Add dpaa2_dev_qbman_pull() to build a pull descriptor (channel or FQ) in one place, and dpaa2_dev_rx_active_dq_storage() (exported internal) to prime the first in-flight VDQ. Replace the open-coded pull-descriptor setup in the Rx, Tx-conf, loopback and event-scheduler paths with these helpers, removing the duplicated dpaa2_qbman_pull_desc_channel_set() in dpaa2_scheduler.c. Rx fast path: - Drive dpaa2_dev_prefetch_rx_common() / dpaa2_dev_rx_common() with function pointers (dpaa2_dev_rx_cb / dpaa2_dev_dq_prefetch) resolved once per burst instead of re-checking the SoC family, callback and parse/ timestamp conditions on every packet. On LX2160A the parser-result prefetch collapses to a no-op (dpaa2_dev_prefetch_next_psr_dummy). - Split fd-to-mbuf so the common case uses the lightweight dpaa2_dev_rx_fd_to_mbuf_core(); the annotation prefetch, parse-offset, timestamp and parser-print steps are selected once per burst via dpaa2_dev_rx_fd_to_mbuf() only when actually enabled. - Merge the channel (CDAN/interrupt) and non-channel (polling) burst routines; by_channel is derived from dpaa2_q->napi_dpcon. dpaa2_dev_rx_channel() / dpaa2_dev_prefetch_rx_channel(), their prototypes and the start-time rx_pkt_burst reassignment are removed. - Rework the Rx error-dump as a callback (dpaa2_dev_err_rx_fd_to_mbuf) over the shared dequeue core with bulk free, replacing the standalone dpaa2_dev_rx_err_pkts_dump() open-coded VDQ loop. Tx confirmation: - Rewrite dpaa2_dev_tx_conf() on top of dpaa2_dev_prefetch_rx_common() with a dpaa2_dev_tx_cnf_fd_to_mbuf() callback, dropping its large open-coded VDQ loop. Add dpaa2_q->tx_queue back-reference so the conf callback can reach the originating Tx queue for 1588 timestamping. Loopback: - Rebuild dpaa2_dev_loopback_rx() on the shared dequeue core and qbman_swp_enqueue_multiple_desc(), removing another duplicated VDQ loop. Inlining and locality: - Force-inline the small hot helpers with __rte_always_inline and let the cold/slow paths (parse_slow, SG fd-to-mbuf, timestamp read, error dump) stay out of line to improve instruction-cache locality. - Simplify the direct-mbuf Tx fast check and drop the redundant per-packet buf->next warning. These changes remove a large amount of duplicated dequeue code and reduce per-packet work and branches on the common forwarding path. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 1 + drivers/event/dpaa2/dpaa2_scheduler.c | 53 +- drivers/net/dpaa2/dpaa2_ethdev.c | 44 +- drivers/net/dpaa2/dpaa2_ethdev.h | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 879 +++++++++--------------- 5 files changed, 357 insertions(+), 644 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 95c7203aa2..3a92a1c0de 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -200,6 +200,7 @@ struct __rte_cache_aligned dpaa2_queue { struct dpaa2_bp_info *bp_array; /*to store tx_conf_queue corresponding to tx_queue*/ struct dpaa2_queue *tx_conf_queue; + struct dpaa2_queue *tx_queue; int32_t eventfd; /*!< Event Fd of this queue */ uint16_t nb_desc; uint16_t tm_sw_td; /*!< TM software taildrop */ diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c b/drivers/event/dpaa2/dpaa2_scheduler.c index 9e58b4253f..a80ec05add 100644 --- a/drivers/event/dpaa2/dpaa2_scheduler.c +++ b/drivers/event/dpaa2/dpaa2_scheduler.c @@ -74,19 +74,6 @@ dpaa2_scheduler_dq_storage_init(struct dpaa2_sch_dev *sch_dev) return ret; } -static inline void -dpaa2_qbman_pull_desc_channel_set(struct qbman_pull_desc *pulldesc, - uint32_t num, uint16_t ch_id, struct qbman_result *dq_sch_storage, - uint64_t iova_storage) -{ - qbman_pull_desc_clear(pulldesc); - qbman_pull_desc_set_numframes(pulldesc, num); - qbman_pull_desc_set_channel(pulldesc, ch_id, - qbman_pull_type_prio); - qbman_pull_desc_set_storage(pulldesc, dq_sch_storage, - iova_storage, 1); -} - static inline struct rte_mbuf * dpaa2_scheduler_swp_mbuf_dq(struct qbman_swp *swp) { @@ -255,8 +242,8 @@ dpaa2_scheduler_recv(struct dpaa2_sch_dev *sch_dev, do { is_last = false; next_pull = false; - dpaa2_qbman_pull_desc_channel_set(&pulldesc, nb_pkts, ch_id, - dq_sch_storage, iova_storage); + dpaa2_dev_qbman_pull(&pulldesc, ch_id, nb_pkts, dq_sch_storage, + iova_storage, true, qbman_pull_type_prio); while (1) { if (qbman_swp_pull(swp, &pulldesc)) { @@ -344,36 +331,10 @@ dpaa2_scheduler_prefetch_recv(struct dpaa2_sch_dev *sch_dev, pull_size = (nb_pkts > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_pkts; - if (likely(q_storage->active_dqs)) - goto pull_active_dqs; - - q_storage->toggle = 0; - dq_storage = q_storage->dq_storage[q_storage->toggle]; - iova_storage = q_storage->iova_dq_storage[q_storage->toggle]; - q_storage->last_num_pkts = pull_size; - dpaa2_qbman_pull_desc_channel_set(&pulldesc, nb_pkts, - ch_id, dq_storage, iova_storage); - if (check_swp_active_dqs(ethrx_dpio_dev->index)) { - do { - active = get_swp_active_dqs(ethrx_dpio_dev->index); - if (qbman_check_command_complete(active)) - break; - } while (1); - clear_swp_active_dqs(ethrx_dpio_dev->index); - } - while (1) { - if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_EVENTDEV_DEBUG("Line(%d): QBMAN is busy", __LINE__); - /* Portal was busy, try again */ - continue; - } - break; + if (likely(q_storage->active_dqs)) { + dpaa2_dev_rx_active_dq_storage(q_storage, ethrx_dpio_dev, + ch_id, pull_size, true, qbman_pull_type_prio); } - q_storage->active_dqs = dq_storage; - q_storage->active_dpio_id = ethrx_dpio_dev->index; - set_swp_active_dqs(ethrx_dpio_dev->index, dq_storage); - -pull_active_dqs: dq_storage = q_storage->active_dqs; rte_prefetch0((void *)(size_t)(dq_storage)); @@ -385,8 +346,8 @@ dpaa2_scheduler_prefetch_recv(struct dpaa2_sch_dev *sch_dev, q_storage->toggle ^= 1; dq_storage1 = q_storage->dq_storage[q_storage->toggle]; iova_storage = q_storage->iova_dq_storage[q_storage->toggle]; - dpaa2_qbman_pull_desc_channel_set(&pulldesc, nb_pkts, - ch_id, dq_storage1, iova_storage); + dpaa2_dev_qbman_pull(&pulldesc, ch_id, nb_pkts, dq_storage1, + iova_storage, true, qbman_pull_type_prio); while (!qbman_check_command_complete(dq_storage)) ; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f00f906040..c91dfb7893 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1826,6 +1826,7 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, tc_id = dpaa2_tx_conf_q->tc_index; flow_id = dpaa2_tx_conf_q->flow_id; dpaa2_q->tx_conf_queue = dpaa2_tx_conf_q; + dpaa2_tx_conf_q->tx_queue = dpaa2_q; qopt |= DPNI_QUEUE_OPT_USER_CTX; tx_conf_cfg.user_context = (size_t)(dpaa2_q); ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, @@ -1965,9 +1966,7 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || dev->rx_pkt_burst == dpaa2_dev_rx || - dev->rx_pkt_burst == dpaa2_dev_loopback_rx || - dev->rx_pkt_burst == dpaa2_dev_rx_channel || - dev->rx_pkt_burst == dpaa2_dev_prefetch_rx_channel) { + dev->rx_pkt_burst == dpaa2_dev_loopback_rx) { *no_of_elements = RTE_DIM(ptypes); return ptypes; } @@ -2232,30 +2231,10 @@ dpaa2_dev_start(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - /* napi: FQs are scheduled to their DPCON at rx_queue_setup, not here; just - * select the channel burst (the worker subscribes its portal later) - */ - if (dev->data->dev_conf.intr_conf.rxq) { - for (i = 0; i < data->nb_rx_queues; i++) { - dpaa2_q = data->rx_queues[i]; - /* the channel burst below derefs napi_dpcon, so every - * rx queue must own a channel - */ - if (!dpaa2_q->napi_dpcon) { - DPAA2_PMD_ERR("napi: rxq %d has no DPCON channel", i); - return -ENODEV; - } - } - if (priv->flags & DPAA2_NO_PREFETCH_RX) - dev->rx_pkt_burst = dpaa2_dev_rx_channel; - else - dev->rx_pkt_burst = dpaa2_dev_prefetch_rx_channel; - } - ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token); if (ret) { DPAA2_PMD_ERR("Failure in enabling dpni %d device: err=%d", - priv->hw_id, ret); + priv->hw_id, ret); return ret; } @@ -2265,8 +2244,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) DPNI_QUEUE_RX, dpaa2_q->tc_index, dpaa2_q->flow_id, &cfg, &qid); if (ret) { - DPAA2_PMD_ERR("Error in getting flow information: " - "err=%d", ret); + DPAA2_PMD_ERR("Error in getting flow information: err=%d", ret); return ret; } dpaa2_q->fqid = qid.fqid; @@ -2274,10 +2252,9 @@ dpaa2_dev_start(struct rte_eth_dev *dev) if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, - DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); + DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { - DPAA2_PMD_ERR("Error getting rx err flow information: err=%d", - ret); + DPAA2_PMD_ERR("Error getting rx err flow information: err=%d", ret); return ret; } dpaa2_q = priv->rx_err_vq; @@ -2300,11 +2277,9 @@ dpaa2_dev_start(struct rte_eth_dev *dev) } err_cfg.set_frame_annotation = true; - ret = dpni_set_errors_behavior(dpni, CMD_PRI_LOW, - priv->token, &err_cfg); + ret = dpni_set_errors_behavior(dpni, CMD_PRI_LOW, priv->token, &err_cfg); if (ret) { - DPAA2_PMD_ERR("Error to dpni_set_errors_behavior: code = %d", - ret); + DPAA2_PMD_ERR("Error to dpni_set_errors_behavior: code = %d", ret); return ret; } @@ -2313,8 +2288,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dev->data->dev_conf.intr_conf.lsc != 0) { /* Registering LSC interrupt handler */ rte_intr_callback_register(intr_handle, - dpaa2_interrupt_handler, - (void *)dev); + dpaa2_interrupt_handler, dev); /* enable vfio intr/eventfd mapping * Interrupt index 0 is required, so we can not use diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 91414114ac..d1ddea7c64 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -933,6 +933,26 @@ int dpaa2_eth_eventq_detach(const struct rte_eth_dev *dev, __rte_internal int dpaa2_eth_eventq_detach_by_rxq(struct dpaa2_queue *dpaa2_ethq); +static __rte_always_inline void +dpaa2_dev_qbman_pull(struct qbman_pull_desc *pulldesc, uint32_t id, + uint8_t numframes, struct qbman_result *v_storage, uint64_t p_storage, + bool by_channel, enum qbman_pull_type_e dct) +{ + qbman_pull_desc_clear(pulldesc); + qbman_pull_desc_set_numframes(pulldesc, numframes); + if (by_channel) + qbman_pull_desc_set_channel(pulldesc, id, dct); + else + qbman_pull_desc_set_fq(pulldesc, id); + qbman_pull_desc_set_storage(pulldesc, v_storage, p_storage, 1); +} + +__rte_internal +void +dpaa2_dev_rx_active_dq_storage(struct queue_storage_info_t *q_storage, + struct dpaa2_dpio_dev *dpio, uint32_t id, uint32_t pull_size, + bool by_channel, enum qbman_pull_type_e dct); + uint16_t dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); uint16_t dpaa2_dev_loopback_rx(void *queue, struct rte_mbuf **bufs, @@ -940,10 +960,6 @@ uint16_t dpaa2_dev_loopback_rx(void *queue, struct rte_mbuf **bufs, uint16_t dpaa2_dev_prefetch_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); -uint16_t dpaa2_dev_prefetch_rx_channel(void *queue, struct rte_mbuf **bufs, - uint16_t nb_pkts); -uint16_t dpaa2_dev_rx_channel(void *queue, struct rte_mbuf **bufs, - uint16_t nb_pkts); void dpaa2_dev_process_parallel_event(struct dpaa2_dpio_dev *dpio_dev, const struct qbman_fd *fd, const struct qbman_result *dq, diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 6d12e6818d..0df758148c 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -40,7 +40,13 @@ #define DPAA2_FAST_PATH_PTYPE_ETH_IPV6_TCP \ (DPAA2_FAST_PATH_PTYPE_ETH_IPV6 | RTE_PTYPE_L4_TCP) -static inline void +typedef void (*dpaa2_dev_rx_cb)(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fd, const struct qbman_fd **fds, + struct rte_mbuf **mbuf); + +typedef void (*dpaa2_dev_dq_prefetch)(const struct qbman_result *dq); + +static __rte_always_inline void dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) { size_t fd_addr; @@ -51,7 +57,7 @@ dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) rte_prefetch0(hw_annot_addr); } -static inline void +static __rte_always_inline void dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, struct rte_mbuf *mbuf, const struct qbman_fd *fd) { @@ -132,7 +138,7 @@ rte_pmd_dpaa2_rx_get_offset(uint16_t port_id, struct rte_mbuf *m, * ID is programmed and the mbuf is carried in the FLC to be freed once * the confirmation is dequeued. */ -static inline void +static __rte_always_inline void dpaa2_mbuf_to_conf_contig_fd(struct rte_mbuf *mbuf, struct qbman_fd *fd) { DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(mbuf)); @@ -145,7 +151,7 @@ dpaa2_mbuf_to_conf_contig_fd(struct rte_mbuf *mbuf, struct qbman_fd *fd) DPAA2_SET_FD_FLC(fd, mbuf); } -static inline void +static __rte_always_inline void dpaa2_dev_rx_mbuf_flc_offload(struct rte_mbuf *m, const struct qbman_fd *fd) { @@ -172,7 +178,41 @@ void dpaa2_dev_rx_mbuf_flc_offload_export(struct rte_mbuf *m, dpaa2_dev_rx_mbuf_flc_offload(m, fd); } -static inline void +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_rx_active_dq_storage) +void +dpaa2_dev_rx_active_dq_storage(struct queue_storage_info_t *q_storage, + struct dpaa2_dpio_dev *dpio, uint32_t id, uint32_t pull_size, + bool by_channel, enum qbman_pull_type_e dct) +{ + struct qbman_result *dq_storage; + struct qbman_pull_desc pulldesc; + struct qbman_swp *swp = dpio->sw_portal; + int ret; + + q_storage->toggle = 0; + dq_storage = q_storage->dq_storage[q_storage->toggle]; + q_storage->last_num_pkts = pull_size; + dpaa2_dev_qbman_pull(&pulldesc, id, pull_size, dq_storage, + q_storage->iova_dq_storage[q_storage->toggle], + by_channel, dct); + if (check_swp_active_dqs(dpio->index)) { + while (!qbman_check_command_complete(get_swp_active_dqs(dpio->index))) + ; + clear_swp_active_dqs(dpio->index); + } + while (1) { + ret = qbman_swp_pull(swp, &pulldesc); + if (unlikely(ret)) + DPAA2_PMD_DP_DEBUG("%s: Failed(%d) to pull", __func__, ret); + else + break; + } + q_storage->active_dqs = dq_storage; + q_storage->active_dpio_id = dpio->index; + set_swp_active_dqs(dpio->index, dq_storage); +} + +static void dpaa2_dev_rx_read_timestamp(struct dpaa2_dev_priv *priv, struct rte_mbuf *m) { @@ -194,7 +234,7 @@ dpaa2_dev_rx_read_timestamp(struct dpaa2_dev_priv *priv, dpaa2_timestamp_debug(priv, __func__, priv->rx_timestamp); } -static inline void __rte_hot +static __rte_always_inline void __rte_hot dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, struct rte_mbuf *m, const struct qbman_fd *fd, void *hw_annot_addr, int is_vlan) @@ -270,9 +310,9 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, frc_u.u16, m->packet_type, m->ol_flags); } -static inline uint32_t __rte_hot +static uint32_t dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation) + struct dpaa2_annot_hdr *annotation) { uint32_t pkt_type = RTE_PTYPE_UNKNOWN; uint16_t *vlan_tci; @@ -364,7 +404,7 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, return pkt_type; } -static inline uint32_t __rte_hot +static uint32_t dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, struct rte_mbuf *mbuf, void *hw_annot_addr) { @@ -410,7 +450,7 @@ dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, return dpaa2_dev_rx_parse_slow(mbuf, annotation); } -static inline struct rte_mbuf *__rte_hot +static struct rte_mbuf * dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; @@ -493,7 +533,7 @@ dpaa2_eth_sg_fd_to_mbuf_export(struct dpaa2_dev_priv *priv, const struct qbman_f return dpaa2_eth_sg_fd_to_mbuf(priv, fd); } -static inline struct rte_mbuf *__rte_hot +static __rte_always_inline struct rte_mbuf *__rte_hot dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); @@ -503,11 +543,8 @@ dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) int is_vlan = false; if (unlikely(dpaa2_svr_family == SVR_LX2160A && - (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & DPAA2_PKT_TYPE_VLAN))) { - rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); - rte_prefetch0(hw_annot_addr); + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & DPAA2_PKT_TYPE_VLAN))) is_vlan = true; - } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -576,7 +613,7 @@ static void dpaa2_dev_tx_enable_tstamp(struct qbman_fd *fd) DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD); } -static inline struct rte_mbuf * +static struct rte_mbuf * dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) { struct rte_mbuf *mc = rte_pktmbuf_alloc(mp); @@ -596,7 +633,7 @@ dpaa2_dev_mbuf_copy_one_seg(const struct rte_mbuf *sgm, struct rte_mempool *mp) return mc; } -static inline void +static __rte_always_inline void dpaa2_dev_tx_config_dynamic_confirm(struct qbman_fd *fd, struct dpaa2_queue *txq, int enable, int tstamp) { @@ -604,24 +641,21 @@ dpaa2_dev_tx_config_dynamic_confirm(struct qbman_fd *fd, void *fd_va = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); if (tstamp) { - DPAA2_SET_FD_FRC(fd, - DPAA2_GET_FD_FRC(fd) | + DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | DPAA2_FD_FRC_FAEADV | DPAA2_FD_FRC_FASV); fd->simple.ctrl |= DPAA2_FD_CTRL_ASAL; } else { - DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | - DPAA2_FD_FRC_FAEADV); + DPAA2_SET_FD_FRC(fd, DPAA2_GET_FD_FRC(fd) | DPAA2_FD_FRC_FAEADV); } /* enable update of confirmation frame annotation */ - fd_faead = (void *)((size_t)fd_va + - DPAA2_FD_PTA_SIZE + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); + fd_faead = (void *)((size_t)fd_va + DPAA2_FD_PTA_SIZE + + DPAA2_FD_HW_ANNOT_FAEAD_OFFSET); if (enable) { fd_faead->fqid = txq->tx_conf_queue->fqid; fd_faead->ctrl = DPAA2_TX_CONFIRM_ENABLE; if (tstamp) { fd_faead->ctrl |= (DPAA2_ANNOT_FAEAD_A2V | - DPAA2_ANNOT_FAEAD_UPDV | - DPAA2_ANNOT_FAEAD_UPD); + DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD); } } else { fd_faead->fqid = 0; @@ -845,7 +879,7 @@ dpaa2_dev_tx_mbuf_to_sg_fd(struct rte_mempool *hw_mp, return 0; } -static inline void +static void dpaa2_dev_prefetch_next_psr(const struct qbman_result *dq) { const struct qbman_fd *fd; @@ -862,6 +896,12 @@ dpaa2_dev_prefetch_next_psr(const struct qbman_result *dq) rte_prefetch0(&annotation->word3); } +static __rte_always_inline void +dpaa2_dev_prefetch_next_psr_dummy(const struct qbman_result *dq) +{ + RTE_SET_USED(dq); +} + static int __rte_noinline __rte_hot dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, struct rte_mbuf *mbuf, struct qbman_fd *fd, @@ -910,117 +950,6 @@ dpaa2_dev_tx_mbuf_to_simple_fd(struct rte_mempool *hw_mp, return ret; } -static void -dpaa2_dev_rx_err_pkts_dump(struct dpaa2_queue *dpaa2_q) -{ - /* Function receive frames for a given device and VQ */ - struct qbman_result *dq_storage; - uint32_t fqid = dpaa2_q->fqid; - int ret, num_rx = 0, i; - uint8_t pending, status; - const uint8_t *buf; - struct qbman_swp *swp; - const struct qbman_fd *fd; - struct qbman_pull_desc pulldesc; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - uint32_t lcore_id = rte_lcore_id(); - void *v_addr, *hw_annot_addr; - struct dpaa2_fas *fas; - struct rte_mbuf *mbuf, *seg; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(!DPAA2_PER_LCORE_DPIO)) { - ret = dpaa2_affine_qbman_swp(); - if (ret) { - DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); - return; - } - } - swp = DPAA2_PER_LCORE_PORTAL; - - dq_storage = dpaa2_q->q_storage[lcore_id]->dq_storage[0]; - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_fq(&pulldesc, fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - qbman_pull_desc_set_numframes(&pulldesc, dpaa2_dqrr_size); - - while (1) { - if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued.QBMAN is busy"); - /* Portal was busy, try again */ - continue; - } - break; - } - - /* Check if the previous issued command is completed. */ - while (!qbman_check_command_complete(dq_storage)) - ; - - pending = 1; - do { - /* Loop until the dq_storage is updated with - * new token by QBMAN - */ - while (!qbman_check_new_result(dq_storage)) - ; - - /* Check whether Last Pull command is Expired and - * setting Condition for Loop termination - */ - if (qbman_result_DQ_is_pull_complete(dq_storage)) { - pending = 0; - /* Check for valid frame. */ - status = qbman_result_DQ_flags(dq_storage); - if (unlikely(!(status & QBMAN_DQ_STAT_VALIDFRAME))) - continue; - } - fd = qbman_result_DQ_fd(dq_storage); - v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); - hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); - fas = hw_annot_addr; - - if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) - dpaa2_dev_rx_annot_prefetch(fd); - if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); - else - mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); - if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) - dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - - dpaa2_dev_rx_read_timestamp(priv, mbuf); - - dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); - DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); - DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", - DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd), - fas->status); - - __rte_mbuf_sanity_check(mbuf, 1); - if (mbuf->nb_segs > 1) { - seg = mbuf; - i = 0; - while (seg) { - buf = rte_pktmbuf_mtod(seg, const uint8_t *); - dpaa2_dump_print("Payload seg[%d]\n", i); - dpaa2_dump_hex_print(buf, seg->data_len); - seg = seg->next; - i++; - } - } else { - buf = rte_pktmbuf_mtod(mbuf, const uint8_t *); - dpaa2_dump_hex_print(buf, mbuf->data_len); - } - rte_pktmbuf_free(mbuf); - dq_storage++; - num_rx++; - } while (pending); - - dpaa2_q->err_pkts += num_rx; -} - /* This function assumes that caller will be keep the same value for nb_pkts * across calls per queue, if that is not the case, better use non-prefetch * version of rx call. @@ -1028,26 +957,23 @@ dpaa2_dev_rx_err_pkts_dump(struct dpaa2_queue *dpaa2_q) * the current nb_pkts or bufs space. */ static __rte_always_inline uint16_t -dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, - uint16_t nb_pkts, bool by_channel) +dpaa2_dev_prefetch_rx_common(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fds[], struct rte_mbuf **bufs, uint16_t nb_pkts, + dpaa2_dev_rx_cb rx_cb, dpaa2_dev_dq_prefetch dq_prefetch) { /* Function receive frames for a given device and VQ*/ - struct dpaa2_queue *dpaa2_q = queue; struct qbman_result *dq_storage, *dq_storage1 = NULL; - int ret, num_rx = 0, pull_size; + int ret, num_rx = 0; + bool by_channel = dpaa2_q->napi_dpcon ? true : false; + uint32_t id, pull_size; uint8_t pending, status; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) - dpaa2_dev_rx_err_pkts_dump(priv->rx_err_vq); - if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); if (ret) { @@ -1056,47 +982,15 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, } } - if (!by_channel && unlikely(!rte_dpaa2_bpid_info && - rte_eal_process_type() == RTE_PROC_SECONDARY)) - rte_dpaa2_bpid_info = dpaa2_q->bp_array; - swp = DPAA2_PER_LCORE_ETHRX_PORTAL; + if (dpaa2_q->napi_dpcon) + id = dpaa2_q->napi_dpcon->qbman_ch_id; + else + id = dpaa2_q->fqid; pull_size = (nb_pkts > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_pkts; if (unlikely(!q_storage->active_dqs)) { - q_storage->toggle = 0; - dq_storage = q_storage->dq_storage[q_storage->toggle]; - q_storage->last_num_pkts = pull_size; - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_numframes(&pulldesc, - q_storage->last_num_pkts); - if (by_channel) - qbman_pull_desc_set_channel(&pulldesc, - dpaa2_q->napi_dpcon->qbman_ch_id, - qbman_pull_type_active); - else - qbman_pull_desc_set_fq(&pulldesc, dpaa2_q->fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (uint64_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) { - while (!qbman_check_command_complete( - get_swp_active_dqs( - DPAA2_PER_LCORE_ETHRX_DPIO->index))) - ; - clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index); - } - while (1) { - if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued." - " QBMAN is busy (1)"); - /* Portal was busy, try again */ - continue; - } - break; - } - q_storage->active_dqs = dq_storage; - q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index; - set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index, - dq_storage); + dpaa2_dev_rx_active_dq_storage(q_storage, DPAA2_PER_LCORE_ETHRX_DPIO, + id, pull_size, by_channel, qbman_pull_type_active); } dq_storage = q_storage->active_dqs; @@ -1108,16 +1002,9 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, */ q_storage->toggle ^= 1; dq_storage1 = q_storage->dq_storage[q_storage->toggle]; - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_numframes(&pulldesc, pull_size); - if (by_channel) - qbman_pull_desc_set_channel(&pulldesc, - dpaa2_q->napi_dpcon->qbman_ch_id, - qbman_pull_type_active); - else - qbman_pull_desc_set_fq(&pulldesc, dpaa2_q->fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage1, - (uint64_t)(DPAA2_VADDR_TO_IOVA(dq_storage1)), 1); + dpaa2_dev_qbman_pull(&pulldesc, id, pull_size, dq_storage1, + q_storage->iova_dq_storage[q_storage->toggle], + by_channel, qbman_pull_type_active); /* Check if the previous issued command is completed. * Also seems like the SWP is shared between the Ethernet Driver @@ -1144,27 +1031,14 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, pending = 0; /* Check for valid frame. */ status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) + if (unlikely(!(status & QBMAN_DQ_STAT_VALIDFRAME))) continue; } - if (dpaa2_svr_family != SVR_LX2160A) - /** Packet type is parsed from FRC for LX2160A.*/ - dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); - if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) - dpaa2_dev_rx_annot_prefetch(fd); - if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); - else - bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); - if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) - dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - - dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); - - dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); + dq_prefetch(dq_storage); + rx_cb(dpaa2_q, fd, &fds[num_rx], &bufs[num_rx]); dq_storage++; num_rx++; @@ -1179,8 +1053,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, /* issue a volatile dequeue command for next pull */ while (1) { if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued." - "QBMAN is busy (2)"); + DPAA2_PMD_DP_DEBUG("QBMAN is busy (2)"); continue; } break; @@ -1194,25 +1067,127 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, return num_rx; } -uint16_t __rte_hot -dpaa2_dev_prefetch_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) +static __rte_always_inline void __rte_hot +dpaa2_dev_rx_fd_to_mbuf_core(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fd, const struct qbman_fd **fds, + struct rte_mbuf **mbuf) +{ + struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; + + RTE_SET_USED(fds); + + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + *mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); + else + *mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); +} + +static __rte_always_inline void +dpaa2_dev_rx_fd_to_mbuf(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fd, const struct qbman_fd **fds, + struct rte_mbuf **mbuf) { - return dpaa2_dev_prefetch_rx_common(queue, bufs, nb_pkts, false); + struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; + + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_annot_prefetch(fd); + dpaa2_dev_rx_fd_to_mbuf_core(dpaa2_q, fd, fds, mbuf); + if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) + dpaa2_dev_rx_parse_offset(priv, *mbuf, fd); + dpaa2_dev_rx_read_timestamp(priv, *mbuf); + dpaa2_dev_rx_print_parser_result(priv, fd, *mbuf); } -/* rx interrupt/CDAN path: each Rx FQ is scheduled to its own DPCON channel, - * which a CDAN notifies on empty->non-empty. A VDQ on a scheduled FQ never - * completes, so the channel is drained by a volatile pull on the CHANNEL (not - * the FQID); one FQ per channel, so no demux is needed. Same prefetch pipeline - * as dpaa2_dev_prefetch_rx (one VDQ kept in flight to mask the ~700 cycle - * latency); the portal's single in-flight VDQ (global_active_dqs) must be +static void +dpaa2_dev_err_rx_fd_to_mbuf(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fd, const struct qbman_fd **fds, + struct rte_mbuf **m) +{ + void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); + struct dpaa2_fas *fas = hw_annot_addr; + struct rte_mbuf *mbuf, *seg; + uint32_t i; + const uint8_t *buf; + + dpaa2_dev_rx_fd_to_mbuf(dpaa2_q, fd, fds, m); + DPAA2_PMD_ERR("Err pkt on port[%d]:", dpaa2_q->eth_data->port_id); + DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", + DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ERR(fd), fas->status); + + mbuf = *m; + __rte_mbuf_sanity_check(mbuf, 1); + if (mbuf->nb_segs > 1) { + seg = mbuf; + i = 0; + while (seg) { + buf = rte_pktmbuf_mtod(seg, const uint8_t *); + dpaa2_dump_print("Payload seg[%d]\n", i); + dpaa2_dump_hex_print(buf, seg->data_len); + seg = seg->next; + i++; + } + } else { + buf = rte_pktmbuf_mtod(mbuf, const uint8_t *); + dpaa2_dump_print("Payload\n"); + dpaa2_dump_hex_print(buf, mbuf->data_len); + } +} + +static void +dpaa2_dev_rx_fd_cb(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fd, const struct qbman_fd **fds, + struct rte_mbuf **mbuf) +{ + RTE_SET_USED(dpaa2_q); + RTE_SET_USED(mbuf); + *fds = fd; +} + +static void +dpaa2_dev_prefetch_rx_err_pkts_dump(struct dpaa2_queue *err_rxq) +{ + uint16_t num_rx; + struct rte_mbuf *mbuf[dpaa2_dqrr_size]; + + num_rx = dpaa2_dev_prefetch_rx_common(err_rxq, NULL, mbuf, dpaa2_dqrr_size, + dpaa2_dev_err_rx_fd_to_mbuf, dpaa2_dev_prefetch_next_psr_dummy); + err_rxq->err_pkts += num_rx; + rte_pktmbuf_free_bulk(mbuf, num_rx); +} + +/* Support both rx interrupt path and polling path, For interrupt path, each Rx FQ + * is scheduled to its own DPCON channel, which a CDAN notifies on empty->non-empty. + * A VDQ on a scheduled FQ never completes, so the channel is drained by a volatile pull + * on the CHANNEL (not the FQID); one FQ per channel, so no demux is needed. + * Same prefetch pipeline as dpaa2_dev_prefetch_rx (one VDQ kept in flight to mask + * the ~700 cycle latency); the portal's single in-flight VDQ (global_active_dqs) must be * quiesced before an interrupt sleep. */ uint16_t __rte_hot -dpaa2_dev_prefetch_rx_channel(void *queue, struct rte_mbuf **bufs, - uint16_t nb_pkts) +dpaa2_dev_prefetch_rx(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) { - return dpaa2_dev_prefetch_rx_common(queue, bufs, nb_pkts, true); + struct dpaa2_queue *dpaa2_q = queue; + struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; + dpaa2_dev_dq_prefetch dq_prefetch = dpaa2_svr_family == SVR_LX2160A ? + dpaa2_dev_prefetch_next_psr_dummy : dpaa2_dev_prefetch_next_psr; + + if (unlikely(!rte_dpaa2_bpid_info && + rte_eal_process_type() == RTE_PROC_SECONDARY)) + rte_dpaa2_bpid_info = dpaa2_q->bp_array; + if (unlikely((priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) && + !dpaa2_q->napi_dpcon)) + dpaa2_dev_prefetch_rx_err_pkts_dump(priv->rx_err_vq); + + if (likely(!(priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) && + !(priv->flags & (DPAA2_IEEE1588_RX_TS_FLAG | + DPAA2_RX_PRINT_PSR_RESULT_FLAG)))) { + return dpaa2_dev_prefetch_rx_common(queue, NULL, bufs, nb_pkts, + dpaa2_dev_rx_fd_to_mbuf_core, dq_prefetch); + } + return dpaa2_dev_prefetch_rx_common(queue, NULL, bufs, nb_pkts, + dpaa2_dev_rx_fd_to_mbuf, dq_prefetch); } void __rte_hot @@ -1281,24 +1256,20 @@ dpaa2_dev_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, } static __rte_always_inline uint16_t -dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, - bool by_channel) +dpaa2_dev_rx_common(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fds[], struct rte_mbuf **bufs, uint16_t nb_pkts, + dpaa2_dev_rx_cb rx_cb, dpaa2_dev_dq_prefetch dq_prefetch) { /* Function receive frames for a given device and VQ */ - struct dpaa2_queue *dpaa2_q = queue; struct qbman_result *dq_storage; - uint32_t fqid = dpaa2_q->fqid; - uint16_t num_rx = 0, next_pull = nb_pkts, num_pulled; + uint32_t next_pull = nb_pkts, id, pull_size; + uint16_t num_rx = 0, num_pulled; + bool by_channel = dpaa2_q->napi_dpcon ? true : false; int ret; uint8_t pending, status; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) - dpaa2_dev_rx_err_pkts_dump(priv->rx_err_vq); if (by_channel) { if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1320,32 +1291,22 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, } swp = DPAA2_PER_LCORE_PORTAL; } + if (dpaa2_q->napi_dpcon) + id = dpaa2_q->napi_dpcon->qbman_ch_id; + else + id = dpaa2_q->fqid; do { dq_storage = dpaa2_q->q_storage[0]->dq_storage[0]; - qbman_pull_desc_clear(&pulldesc); - if (by_channel) - qbman_pull_desc_set_channel(&pulldesc, - dpaa2_q->napi_dpcon->qbman_ch_id, - qbman_pull_type_active); - else - qbman_pull_desc_set_fq(&pulldesc, fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - - if (next_pull > dpaa2_dqrr_size) { - qbman_pull_desc_set_numframes(&pulldesc, - dpaa2_dqrr_size); - next_pull -= dpaa2_dqrr_size; - } else { - qbman_pull_desc_set_numframes(&pulldesc, next_pull); - next_pull = 0; - } + pull_size = next_pull > dpaa2_dqrr_size ? dpaa2_dqrr_size : next_pull; + dpaa2_dev_qbman_pull(&pulldesc, id, pull_size, dq_storage, + dpaa2_q->q_storage[0]->iova_dq_storage[0], + by_channel, qbman_pull_type_active); + next_pull -= pull_size; while (1) { if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG( - "VDQ command is not issued.QBMAN is busy"); + DPAA2_PMD_DP_DEBUG("QBMAN is busy"); /* Portal was busy, try again */ continue; } @@ -1373,27 +1334,14 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, pending = 0; /* Check for valid frame. */ status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & - QBMAN_DQ_STAT_VALIDFRAME) == 0)) + if (unlikely(!(status & QBMAN_DQ_STAT_VALIDFRAME))) continue; } - if (dpaa2_svr_family != SVR_LX2160A) - /** Packet type is parsed from FRC for LX2160A.*/ - dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); - if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) - dpaa2_dev_rx_annot_prefetch(fd); - if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); - else - bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); - if (priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) - dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - - dpaa2_dev_rx_read_timestamp(priv, bufs[num_rx]); - dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); + dq_prefetch(dq_storage); + rx_cb(dpaa2_q, fd, &fds[num_rx], &bufs[num_rx]); dq_storage++; num_rx++; @@ -1407,23 +1355,48 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, return num_rx; } -uint16_t -dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) +static void +dpaa2_dev_rx_err_pkts_dump(struct dpaa2_queue *err_rxq) { - return dpaa2_dev_rx_common(queue, bufs, nb_pkts, false); + uint16_t num_rx; + struct rte_mbuf *mbuf[dpaa2_dqrr_size]; + + num_rx = dpaa2_dev_rx_common(err_rxq, NULL, mbuf, dpaa2_dqrr_size, + dpaa2_dev_err_rx_fd_to_mbuf, dpaa2_dev_prefetch_next_psr_dummy); + err_rxq->err_pkts += num_rx; + rte_pktmbuf_free_bulk(mbuf, num_rx); } -/* rx-interrupt path: synchronous volatile dequeue on the queue's DPCON channel - * (no prefetch pipeline, so nothing is left in flight across an interrupt - * sleep, and a channel VDQ -- unlike an FQ VDQ -- completes on a scheduled FQ). +/* Support both rx-interrupt path and polling path, Fo interrupt path: synchronous + * volatile dequeue on the queue's DPCON channel (no prefetch pipeline, so nothing + * is left in flight across an interrupt sleep, and a channel VDQ -- unlike an + * FQ VDQ -- completes on a scheduled FQ). */ -uint16_t __rte_hot -dpaa2_dev_rx_channel(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) +uint16_t +dpaa2_dev_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { - return dpaa2_dev_rx_common(queue, bufs, nb_pkts, true); + struct dpaa2_queue *dpaa2_q = queue; + struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; + dpaa2_dev_dq_prefetch dq_prefetch = dpaa2_svr_family == SVR_LX2160A ? + dpaa2_dev_prefetch_next_psr_dummy : dpaa2_dev_prefetch_next_psr; + + if (unlikely(!rte_dpaa2_bpid_info && + rte_eal_process_type() == RTE_PROC_SECONDARY)) + rte_dpaa2_bpid_info = dpaa2_q->bp_array; + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) + dpaa2_dev_rx_err_pkts_dump(priv->rx_err_vq); + + if (likely(!(priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) && + !(priv->flags & (DPAA2_IEEE1588_RX_TS_FLAG | + DPAA2_RX_PRINT_PSR_RESULT_FLAG)))) { + return dpaa2_dev_rx_common(queue, NULL, bufs, nb_pkts, + dpaa2_dev_rx_fd_to_mbuf_core, dq_prefetch); + } + return dpaa2_dev_rx_common(queue, NULL, bufs, nb_pkts, + dpaa2_dev_rx_fd_to_mbuf, dq_prefetch); } -static inline int +static __rte_always_inline int dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, struct rte_mbuf *mbuf) { @@ -1436,191 +1409,83 @@ dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, return true; } -#define swp_idx (DPAA2_PER_LCORE_ETHRX_DPIO->index) +static __rte_always_inline void __rte_hot +dpaa2_dev_tx_cnf_fd_to_mbuf(struct dpaa2_queue *dpaa2_q, + const struct qbman_fd *fd, const struct qbman_fd **fds, + struct rte_mbuf **mbuf) +{ + void *v_addr; + struct dpaa2_annot_hdr *annotation; + struct dpaa2_queue *dpaa2_txq = dpaa2_q->tx_queue; + struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; + + RTE_SET_USED(fds); + + *mbuf = (void *)DPAA2_GET_FD_FLC(fd); + if (unlikely((*mbuf)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)) { + v_addr = (*mbuf)->buf_addr; + annotation = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); + rte_atomic_store_explicit(&priv->tx_timestamp, + annotation->word2, rte_memory_order_relaxed); + rte_atomic_store_explicit(&priv->next_txq_to_cnf, + dpaa2_txq, rte_memory_order_relaxed); + rte_atomic_fetch_sub_explicit(&dpaa2_q->ts_to_cnfd, 1, + rte_memory_order_relaxed); + dpaa2_timestamp_debug(priv, __func__, priv->tx_timestamp); + } +} uint16_t dpaa2_dev_tx_conf(void *txq, int drain) { /* Function receive frames for a given device and VQ*/ struct dpaa2_queue *dpaa2_txq = txq; struct dpaa2_queue *dpaa2_q = dpaa2_txq->tx_conf_queue; - struct qbman_result *dq_storage, *dq_storage1 = NULL; - uint32_t fqid = dpaa2_q->fqid; - int ret, pull_size, total = 0, bulk_free; - uint8_t pending, status, idx, buf_idx; - struct qbman_swp *swp; - const struct qbman_fd *fd; - struct qbman_pull_desc pulldesc; - struct queue_storage_info_t *q_storage; - struct qbman_result *rst; - + uint16_t num_rx, total = 0, idx; + int bulk_free; struct rte_mbuf *mbufs[dpaa2_dqrr_size]; - struct rte_mempool *mp = NULL; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; - struct dpaa2_annot_hdr *annotation; - void *v_addr; + struct rte_mempool *mp; + dpaa2_dev_dq_prefetch dq_prefetch = dpaa2_svr_family == SVR_LX2160A ? + dpaa2_dev_prefetch_next_psr_dummy : dpaa2_dev_prefetch_next_psr; -conf_again: +dq_again: + num_rx = dpaa2_dev_prefetch_rx_common(dpaa2_q, NULL, mbufs, dpaa2_dqrr_size, + dpaa2_dev_tx_cnf_fd_to_mbuf, dq_prefetch); bulk_free = true; - idx = 0; - q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { - ret = dpaa2_affine_qbman_ethrx_swp(); - if (ret) { - DPAA2_PMD_ERR("Failure in affining portal"); - return 0; - } - } - - swp = DPAA2_PER_LCORE_ETHRX_PORTAL; - pull_size = dpaa2_dqrr_size; - if (unlikely(!q_storage->active_dqs)) { - q_storage->toggle = 0; - dq_storage = q_storage->dq_storage[q_storage->toggle]; - q_storage->last_num_pkts = pull_size; - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_numframes(&pulldesc, - q_storage->last_num_pkts); - qbman_pull_desc_set_fq(&pulldesc, fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage, - DPAA2_VADDR_TO_IOVA(dq_storage), 1); - if (check_swp_active_dqs(swp_idx)) { - rst = get_swp_active_dqs(swp_idx); - while (!qbman_check_command_complete(rst)) - ; - clear_swp_active_dqs(swp_idx); - } - while (1) { - if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("QBMAN is busy (1)"); - /* Portal was busy, try again */ - continue; - } - break; - } - q_storage->active_dqs = dq_storage; - q_storage->active_dpio_id = swp_idx; - set_swp_active_dqs(swp_idx, dq_storage); - } - - dq_storage = q_storage->active_dqs; - rte_prefetch0((void *)(dq_storage)); - rte_prefetch0((void *)(dq_storage + 1)); - - /* Prepare next pull descriptor. This will give space for the - * prefetching done on DQRR entries - */ - q_storage->toggle ^= 1; - dq_storage1 = q_storage->dq_storage[q_storage->toggle]; - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_numframes(&pulldesc, pull_size); - qbman_pull_desc_set_fq(&pulldesc, fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage1, - DPAA2_VADDR_TO_IOVA(dq_storage1), 1); - - /* Check if the previous issued command is completed. - * Also seems like the SWP is shared between the Ethernet Driver - * and the SEC driver. - */ - while (!qbman_check_command_complete(dq_storage)) - ; - if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id)) - clear_swp_active_dqs(q_storage->active_dpio_id); - - pending = 1; - - do { - /* Loop until the dq_storage is updated with - * new token by QBMAN - */ - while (!qbman_check_new_result(dq_storage)) - ; - rte_prefetch0((void *)(dq_storage + 2)); - /* Check whether Last Pull command is Expired and - * setting Condition for Loop termination - */ - if (qbman_result_DQ_is_pull_complete(dq_storage)) { - pending = 0; - /* Check for valid frame. */ - status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) - continue; - } - - fd = qbman_result_DQ_fd(dq_storage); - mbufs[idx] = (void *)DPAA2_GET_FD_FLC(fd); + mp = NULL; + for (idx = 0; idx < num_rx; idx++) { if (unlikely(!mp)) mp = mbufs[idx]->pool; - if (unlikely(rte_mbuf_refcnt_read(mbufs[idx]) > 1)) - bulk_free = false; - if (bulk_free && - !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx])) + if (bulk_free && unlikely(rte_mbuf_refcnt_read(mbufs[idx]) > 1 || + !dpaa2_dev_is_mbuf_from_spec_pool(mp, mbufs[idx]))) bulk_free = false; - if (unlikely(mbufs[idx]->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST)) { - v_addr = mbufs[idx]->buf_addr; - annotation = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); - rte_atomic_store_explicit(&priv->tx_timestamp, - annotation->word2, rte_memory_order_relaxed); - rte_atomic_store_explicit(&priv->next_txq_to_cnf, - dpaa2_txq, rte_memory_order_relaxed); - rte_atomic_fetch_sub_explicit(&dpaa2_q->ts_to_cnfd, 1, - rte_memory_order_relaxed); - dpaa2_timestamp_debug(priv, __func__, priv->tx_timestamp); - } - idx++; - dq_storage++; - if (idx >= dpaa2_dqrr_size) - break; - } while (pending); - - if (check_swp_active_dqs(swp_idx)) { - rst = get_swp_active_dqs(swp_idx); - while (!qbman_check_command_complete(rst)) - ; - clear_swp_active_dqs(swp_idx); - } - /* issue a volatile dequeue command for next pull */ - while (1) { - if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("QBMAN is busy (2)"); - continue; - } - break; } - q_storage->active_dqs = dq_storage1; - q_storage->active_dpio_id = swp_idx; - set_swp_active_dqs(swp_idx, dq_storage1); if (bulk_free) { - rte_pktmbuf_free_bulk(mbufs, idx); + rte_pktmbuf_free_bulk(mbufs, num_rx); } else { - for (buf_idx = 0; buf_idx < idx; buf_idx++) - rte_pktmbuf_free(mbufs[buf_idx]); + for (idx = 0; idx < num_rx; idx++) { + if (rte_mbuf_refcnt_read(mbufs[idx]) > 1) + rte_mbuf_refcnt_update(mbufs[idx], -1); + else + rte_pktmbuf_free(mbufs[idx]); + } } - - dpaa2_q->rx_pkts += idx; - total += idx; - if (drain && pending) - goto conf_again; + total += num_rx; + if (drain && num_rx) + goto dq_again; return total; } -static inline int +static __rte_always_inline int dpaa2_dev_tx_fast_mbuf_to_fd(struct dpaa2_dev_priv *priv, struct rte_mbuf *buf, struct qbman_fd *fd) { struct rte_mempool *mp = buf->pool; if (likely(RTE_MBUF_DIRECT(buf) && - mp && mp->ops_index == - priv->bp_list->dpaa2_ops_index && - buf->nb_segs == 1 && - rte_mbuf_refcnt_read(buf) == 1)) { - if (unlikely(buf->next)) { - DPAA2_PMD_WARN("Single mbuf has next segment(%p)", - buf->next); - } + mp->ops_index == priv->bp_list->dpaa2_ops_index && + buf->nb_segs == 1 && rte_mbuf_refcnt_read(buf) == 1)) { if (unlikely(priv->tx_conf_type == DPAA2_TX_ABSOLUTE_CONF)) dpaa2_mbuf_to_conf_contig_fd(buf, fd); else @@ -2055,26 +1920,23 @@ dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, /* This function loopbacks all the received packets.*/ uint16_t dpaa2_dev_loopback_rx(void *queue, - struct rte_mbuf **bufs __rte_unused, - uint16_t nb_pkts) + struct rte_mbuf **bufs __rte_unused, uint16_t nb_pkts __rte_unused) { /* Function receive frames for a given device and VQ*/ - struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; - struct qbman_result *dq_storage, *dq_storage1 = NULL; - uint32_t fqid = dpaa2_q->fqid; - int ret, num_rx = 0, num_tx = 0, pull_size; - uint8_t pending, status; + struct dpaa2_queue *dpaa2_q = queue; + int ret, num_rx, num_tx = 0, i; struct qbman_swp *swp; - struct qbman_fd *fd[DPAA2_LX2_DQRR_RING_SIZE]; - struct qbman_pull_desc pulldesc; + const struct qbman_fd *fd[dpaa2_dqrr_size]; + struct qbman_fd tx_fd[dpaa2_dqrr_size]; struct qbman_eq_desc eqdesc; - struct queue_storage_info_t *q_storage; - struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; - struct dpaa2_dev_priv *priv = eth_data->dev_private; + struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; struct dpaa2_queue *tx_q = priv->tx_vq[0]; /* todo - currently we are using 1st TX queue only for loopback*/ - q_storage = dpaa2_q->q_storage[rte_lcore_id()]; + qbman_eq_desc_clear(&eqdesc); + qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ); + qbman_eq_desc_set_response(&eqdesc, 0, 0); + qbman_eq_desc_set_fq(&eqdesc, tx_q->fqid); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); if (ret) { @@ -2083,117 +1945,16 @@ dpaa2_dev_loopback_rx(void *queue, } } swp = DPAA2_PER_LCORE_ETHRX_PORTAL; - pull_size = (nb_pkts > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_pkts; - if (unlikely(!q_storage->active_dqs)) { - q_storage->toggle = 0; - dq_storage = q_storage->dq_storage[q_storage->toggle]; - q_storage->last_num_pkts = pull_size; - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_numframes(&pulldesc, - q_storage->last_num_pkts); - qbman_pull_desc_set_fq(&pulldesc, fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); - if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) { - while (!qbman_check_command_complete( - get_swp_active_dqs( - DPAA2_PER_LCORE_ETHRX_DPIO->index))) - ; - clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index); - } - while (1) { - if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG( - "VDQ command not issued.QBMAN busy"); - /* Portal was busy, try again */ - continue; - } - break; - } - q_storage->active_dqs = dq_storage; - q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index; - set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index, - dq_storage); - } - - dq_storage = q_storage->active_dqs; - rte_prefetch0((void *)(size_t)(dq_storage)); - rte_prefetch0((void *)(size_t)(dq_storage + 1)); - - /* Prepare next pull descriptor. This will give space for the - * prefetching done on DQRR entries - */ - q_storage->toggle ^= 1; - dq_storage1 = q_storage->dq_storage[q_storage->toggle]; - qbman_pull_desc_clear(&pulldesc); - qbman_pull_desc_set_numframes(&pulldesc, pull_size); - qbman_pull_desc_set_fq(&pulldesc, fqid); - qbman_pull_desc_set_storage(&pulldesc, dq_storage1, - (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage1)), 1); - - /*Prepare enqueue descriptor*/ - qbman_eq_desc_clear(&eqdesc); - qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ); - qbman_eq_desc_set_response(&eqdesc, 0, 0); - qbman_eq_desc_set_fq(&eqdesc, tx_q->fqid); - - /* Check if the previous issued command is completed. - * Also seems like the SWP is shared between the Ethernet Driver - * and the SEC driver. - */ - while (!qbman_check_command_complete(dq_storage)) - ; - if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id)) - clear_swp_active_dqs(q_storage->active_dpio_id); - - pending = 1; - - do { - /* Loop until the dq_storage is updated with - * new token by QBMAN - */ - while (!qbman_check_new_result(dq_storage)) - ; - rte_prefetch0((void *)((size_t)(dq_storage + 2))); - /* Check whether Last Pull command is Expired and - * setting Condition for Loop termination - */ - if (qbman_result_DQ_is_pull_complete(dq_storage)) { - pending = 0; - /* Check for valid frame. */ - status = qbman_result_DQ_flags(dq_storage); - if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) - continue; - } - fd[num_rx] = RTE_PTR_UNQUAL(qbman_result_DQ_fd(dq_storage)); - - dq_storage++; - num_rx++; - } while (pending); + num_rx = dpaa2_dev_prefetch_rx_common(dpaa2_q, fd, NULL, dpaa2_dqrr_size, + dpaa2_dev_rx_fd_cb, dpaa2_svr_family == SVR_LX2160A ? + dpaa2_dev_prefetch_next_psr_dummy : dpaa2_dev_prefetch_next_psr); + for (i = 0; i < num_rx; i++) + rte_memcpy(&tx_fd[i], fd[i], sizeof(struct qbman_fd)); while (num_tx < num_rx) { - num_tx += qbman_swp_enqueue_multiple_fd(swp, &eqdesc, - &fd[num_tx], 0, num_rx - num_tx); - } - - if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) { - while (!qbman_check_command_complete( - get_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index))) - ; - clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index); + num_tx += qbman_swp_enqueue_multiple_desc(swp, &eqdesc, + &tx_fd[num_tx], num_rx - num_tx); } - /* issue a volatile dequeue command for next pull */ - while (1) { - if (qbman_swp_pull(swp, &pulldesc)) { - DPAA2_PMD_DP_DEBUG("VDQ command is not issued." - "QBMAN is busy (2)"); - continue; - } - break; - } - q_storage->active_dqs = dq_storage1; - q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index; - set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index, dq_storage1); dpaa2_q->rx_pkts += num_rx; dpaa2_q->tx_pkts += num_tx; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 52/65] net/dpaa2: bind per-queue DPIO for rx-queue interrupts 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (50 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 51/65] net/dpaa2: consolidate dequeue paths and optimize fast path Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 53/65] net/dpaa2: add API to clean Tx confirmation queue Prashant Gupta ` (12 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 rx-queue interrupt path never delivered a wakeup to the application. The per-queue wakeup eventfd was published into dev->intr_handle lazily, from inside the arm path (rx_queue_intr_enable), which only runs on the polling lcore just before it sleeps. The generic rte_eth_dev_rx_intr_ctl_q() flow, however, reads dev->intr_handle and registers the application epoll once at setup time, before any arm. It therefore registered an unset/stale fd and never saw the portal DQRI wake edge. Fix the ordering by giving each napi rx queue its own dedicated DPIO (dpaa2_q->napi_dpio), allocated in dpaa2_dev_rx_queue_setup(), and publish that portal's eventfd into dev->intr_handle there - before the application registers its epoll. The one-shot CDAN enable and the in-flight VDQ quiesce stay in rx_queue_intr_enable()/disable(), which run on the polling lcore where q_storage[rte_lcore_id()] is valid; these must not move. Because the queue now owns a fixed DPIO instead of borrowing the per-lcore ethrx portal, the rx burst paths (dpaa2_dev_prefetch_rx_common, dpaa2_dev_rx_common) pull on dpaa2_q->napi_dpio and re-affine it to the current lcore on migration. This removes the napi_sub_dpio atomic subscribe/re-home dance and the shared-portal ethrx_intr_refcnt bookkeeping. The DPIO interrupt affinity, stashing and cpufreq-governor setup are consolidated into dpaa2_dpio_intr_thread_affinity()/_restore(), and rte_dpaa2_alloc_dpio_device() gains a build_epoll argument so the rx-queue intr path (application epoll) and the eventdev path (private epoll) can share one allocator. Internal-only helpers (intr_affinity_set, configure_stashing, cpufreq_governor, dpio_intr_init) are made static. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 156 ++++++++------- drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 23 +-- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 3 +- drivers/event/dpaa2/dpaa2_eventdev.c | 35 +--- drivers/net/dpaa2/dpaa2_ethdev.c | 234 +++++++++-------------- drivers/net/dpaa2/dpaa2_rxtx.c | 67 ++++--- 6 files changed, 234 insertions(+), 284 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index 17af74aad8..a32406b1b3 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -112,13 +112,13 @@ dpaa2_get_core_id(void) return cpu_id; } -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_affinity_set) -int dpaa2_dpio_intr_affinity_set(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) +static int +dpaa2_dpio_intr_affinity_set(struct dpaa2_dpio_dev *dpio_dev) { char line[512], match[32], path[64]; FILE *fp; long irq = -1; - int32_t dpio_id = dpio_dev->hw_id, ret = 0; + int32_t dpio_id = dpio_dev->hw_id, cpu_id = dpio_dev->cpu_affine, ret = 0; #define IRQ_ALL_F "/proc/interrupts" #define IRQ_SMP_AFFINITY_F "/proc/irq/%ld/smp_affinity_list" @@ -200,22 +200,6 @@ int dpaa2_dpio_intr_affinity_set(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) return ret; } -/* Pin the dpio's MSI IRQ to the calling lcore's core (best-effort), so a - * worker sleeping on this portal's eventfd is woken on its own core. - */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_affine_intr_to_core) -void -dpaa2_dpio_affine_intr_to_core(struct dpaa2_dpio_dev *dpio_dev) -{ - int cpu_id = dpaa2_get_core_id(), ret; - - if (cpu_id >= 0) { - ret = dpaa2_dpio_intr_affinity_set(dpio_dev, cpu_id); - if (ret) - DPAA2_BUS_ERR("Failed(%d) to affinity interrupt on core.%d", ret, cpu_id); - } -} - static int _dpaa2_dpio_cpufreq_governor(uint32_t cpu_id, bool restore) { struct dpaa2_dpio_gov_save *gov; @@ -283,8 +267,7 @@ static int _dpaa2_dpio_cpufreq_governor(uint32_t cpu_id, bool restore) return ret; } -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_cpufreq_governor) -int dpaa2_dpio_cpufreq_governor(int cpu_id, bool restore) +static int dpaa2_dpio_cpufreq_governor(int cpu_id, bool restore) { bool governor_all = cpu_id < 0 ? true : false; int ret = 0; @@ -305,14 +288,72 @@ int dpaa2_dpio_cpufreq_governor(int cpu_id, bool restore) return ret; } +static int +dpaa2_dpio_configure_stashing(struct dpaa2_dpio_dev *dpio_dev) +{ + int sdest, ret; + + /* Set the STASH Destination depending on Current CPU ID. + * Valid values of SDEST are 4,5,6,7. Where, + */ + sdest = fslmc_vfio_core_cluster_sdest(dpio_dev->cpu_affine); + DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", + dpio_dev->index, dpio_dev->cpu_affine, sdest); + if (sdest < 0) + return sdest; + + ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, + dpio_dev->token, sdest); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to set stashing(%02x) of dpio.%d/cpu.%d", + ret, sdest, dpio_dev->hw_id, dpio_dev->cpu_affine); + } + + return ret; +} + +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_thread_affinity) +void dpaa2_dpio_intr_thread_affinity(struct dpaa2_dpio_dev *dpio_dev) +{ + int ret; + + ret = dpaa2_dpio_intr_affinity_set(dpio_dev); + if (ret) { + DPAA2_BUS_WARN("Failed(%d) to affinity dpio.%d's interrupt on core%d", + ret, dpio_dev->hw_id, dpio_dev->cpu_affine); + } + ret = dpaa2_dpio_configure_stashing(dpio_dev); + if (ret) { + DPAA2_BUS_WARN("Failed(%d) to configure dpio.%d's stashing on core%d", + ret, dpio_dev->hw_id, dpio_dev->cpu_affine); + }; + + ret = dpaa2_dpio_cpufreq_governor(dpio_dev->cpu_affine, false); + if (ret) { + DPAA2_BUS_WARN("Failed(%d) to set governor of core%d", + ret, dpio_dev->cpu_affine); + } +} + +RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_thread_restore) +void dpaa2_dpio_intr_thread_restore(struct dpaa2_dpio_dev *dpio_dev) +{ + int ret, cpu_id = dpio_dev ? dpio_dev->cpu_affine : -1; + + ret = dpaa2_dpio_cpufreq_governor(cpu_id, true); + if (ret) { + DPAA2_BUS_WARN("Failed(%d) to restore governor of core%d", + ret, cpu_id); + } +} + /* threshold: DQRR fill raising DQRI (< ring depth); timeout: holdoff in ITP units. * Per-mode values from the caller (eventdev vs rx-queue intr). * The DQRI config is portal-wide and this is idempotent: the first caller to * arm a portal wins, a later caller's values are ignored (a portal normally * serves a single mode). */ -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_intr_init) -int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, +static int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, int timeout, bool build_epoll) { int eventfd, dpio_epoll_fd, ret, index; @@ -412,30 +453,6 @@ void dpaa2_dpio_intr_deinit(struct dpaa2_dpio_dev *dpio_dev) dpio_dev->intr_enabled = false; } -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dpio_configure_stashing) -int -dpaa2_dpio_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id) -{ - int sdest, ret; - - /* Set the STASH Destination depending on Current CPU ID. - * Valid values of SDEST are 4,5,6,7. Where, - */ - sdest = fslmc_vfio_core_cluster_sdest(cpu_id); - DPAA2_BUS_DEBUG("Portal= %d CPU= %u SDEST= %d", dpio_dev->index, cpu_id, sdest); - if (sdest < 0) - return sdest; - - ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, - dpio_dev->token, sdest); - if (ret) { - DPAA2_BUS_ERR("Failed(%d) to set stashing(%02x) of dpio.%d/cpu.%d", - ret, sdest, dpio_dev->hw_id, cpu_id); - } - - return ret; -} - static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) { if (dpio_dev) { @@ -454,28 +471,29 @@ static void dpaa2_put_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) } } -static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(bool ethrx) +static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(void) { struct dpaa2_dpio_dev *dpio_dev; /* Set the Stashing Destination */ int cpu_id = dpaa2_get_core_id(), ret; - dpio_dev = rte_dpaa2_alloc_dpio_device((ethrx && cpu_id >= 0) ? - true : false, DPAA2_PORTAL_INTR_COALESC_DISABLE, cpu_id); + dpio_dev = rte_dpaa2_alloc_dpio_device(false, DPAA2_PORTAL_INTR_COALESC_DISABLE, + cpu_id, false); if (!dpio_dev) { DPAA2_BUS_ERR("No software portal resource left"); return NULL; } DPAA2_BUS_DEBUG("New Portal %p (%d) affined thread - %u", - dpio_dev, dpio_dev->index, rte_gettid()); + dpio_dev, dpio_dev->index, rte_gettid()); + dpio_dev->cpu_affine = cpu_id; if (cpu_id < 0) { DPAA2_BUS_WARN("Thread not affined to a single core"); if (dpaa2_svr_family != SVR_LX2160A) qbman_swp_update(dpio_dev->sw_portal, 1); } else { - ret = dpaa2_dpio_configure_stashing(dpio_dev, cpu_id); + ret = dpaa2_dpio_configure_stashing(dpio_dev); if (ret) { DPAA2_BUS_ERR("Failed(%d) to configure stashing", ret); rte_atomic_store_explicit(&dpio_dev->ref_count, 0, @@ -483,7 +501,6 @@ static struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(bool ethrx) return NULL; } } - dpio_dev->cpu_affine = cpu_id; ret = pthread_setspecific(dpaa2_portal_key, (void *)dpio_dev); if (ret) { @@ -504,10 +521,10 @@ dpaa2_affine_qbman_swp(void) /* Populate the dpaa2_io_portal structure */ if (!RTE_PER_LCORE(_dpaa2_io).dpio_dev) { - dpio_dev = dpaa2_get_qbman_swp(false); + dpio_dev = dpaa2_get_qbman_swp(); if (!dpio_dev) { DPAA2_BUS_ERR("Error in software portal allocation"); - return -1; + return -ENODEV; } RTE_PER_LCORE(_dpaa2_io).dpio_dev = dpio_dev; @@ -526,10 +543,10 @@ dpaa2_affine_qbman_ethrx_swp(void) /* Populate the dpaa2_io_portal structure */ if (!RTE_PER_LCORE(_dpaa2_io).ethrx_dpio_dev) { - dpio_dev = dpaa2_get_qbman_swp(true); + dpio_dev = dpaa2_get_qbman_swp(); if (!dpio_dev) { DPAA2_BUS_ERR("Error in software portal allocation"); - return -1; + return -ENODEV; } RTE_PER_LCORE(_dpaa2_io).ethrx_dpio_dev = dpio_dev; @@ -551,13 +568,12 @@ static void dpaa2_portal_finish(void *arg) RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_alloc_dpio_device) struct dpaa2_dpio_dev * -rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, int32_t cpu_affine) +rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, + int32_t cpu_affine, bool build_epoll) { struct dpaa2_dpio_dev *dpio_dev = NULL; -#ifdef RTE_EVENT_DPAA2 int ret, timeout = 0xff; char *env; -#endif uint16_t expected = 0; /* Get DPIO dev handle from list using index */ @@ -571,7 +587,9 @@ rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, int32_t cpu_affine) DPAA2_BUS_ERR("No software portal resource left"); return NULL; } - #ifdef RTE_EVENT_DPAA2 + + dpio_dev->cpu_affine = cpu_affine; + if (!isr) goto quit; env = getenv("DPAA2_PORTAL_INTR_THRESHOLD"); @@ -580,28 +598,24 @@ rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, int32_t cpu_affine) if (threshold > DPAA2_PORTAL_INTR_THRESH_MAX) { DPAA2_BUS_ERR("Invalid threshold(%d) from %s", threshold, env ? "environment" : "parameter"); - threshold = DPAA2_PORTAL_INTR_COALESC_DISABLE; + threshold = DPAA2_PORTAL_INTR_COALESC_DISABLE; } env = getenv("DPAA2_PORTAL_INTR_TIMEOUT"); if (env) sscanf(env, "%x", &timeout); - ret = dpaa2_dpio_intr_init(dpio_dev, threshold, timeout, true); + ret = dpaa2_dpio_intr_init(dpio_dev, threshold, timeout, build_epoll); if (ret) { DPAA2_BUS_ERR("Failed(%d) to init DPIO interrupt", ret); rte_atomic_store_explicit(&dpio_dev->ref_count, 0, rte_memory_order_release); + dpio_dev->cpu_affine = -1; return NULL; } - if (cpu_affine >= 0) - dpaa2_dpio_intr_affinity_set(dpio_dev, cpu_affine); -quit: -#else - RTE_SET_USED(isr); - RTE_SET_USED(threshold); -#endif - dpio_dev->cpu_affine = cpu_affine; + if (dpio_dev->cpu_affine >= 0) + dpaa2_dpio_intr_affinity_set(dpio_dev); +quit: return dpio_dev; } diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index 7c089408c5..c61f8ee0a2 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -38,14 +38,11 @@ RTE_DECLARE_PER_LCORE(struct dpaa2_io_portal_t, _dpaa2_io); #define DPAA2_PER_LCORE_DQRR_MBUF(i) \ RTE_PER_LCORE(_dpaa2_io).dpio_dev->dpaa2_held_bufs.mbuf[i] -__rte_internal int -dpaa2_dpio_intr_affinity_set(struct dpaa2_dpio_dev *dpio_dev, int cpu_id); +__rte_internal void +dpaa2_dpio_intr_thread_affinity(struct dpaa2_dpio_dev *dpio_dev); -__rte_internal int -dpaa2_dpio_cpufreq_governor(int cpu_id, bool restore); - -__rte_internal int -dpaa2_dpio_configure_stashing(struct dpaa2_dpio_dev *dpio_dev, int cpu_id); +__rte_internal void +dpaa2_dpio_intr_thread_restore(struct dpaa2_dpio_dev *dpio_dev); /* Affine a DPIO portal to current processing thread */ __rte_internal @@ -55,18 +52,9 @@ int dpaa2_affine_qbman_swp(void); __rte_internal int dpaa2_affine_qbman_ethrx_swp(void); -/* set up / tear down a DPIO portal's DQRI interrupt (rx-queue interrupt mode) */ -__rte_internal -int dpaa2_dpio_intr_init(struct dpaa2_dpio_dev *dpio_dev, int threshold, - int timeout, bool build_epoll); - __rte_internal void dpaa2_dpio_intr_deinit(struct dpaa2_dpio_dev *dpio_dev); -/* pin a DPIO's MSI IRQ to the calling lcore's core (rx-queue interrupt mode) */ -__rte_internal -void dpaa2_dpio_affine_intr_to_core(struct dpaa2_dpio_dev *dpio_dev); - /* allocate memory for FQ - dq storage */ __rte_internal int @@ -84,7 +72,8 @@ dpaa2_free_eq_descriptors(void); __rte_internal struct dpaa2_dpio_dev * -rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, int32_t cpu_affine); +rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, + int32_t cpu_affine, bool build_epoll); __rte_internal void diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 3a92a1c0de..1731999257 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -139,7 +139,6 @@ struct dpaa2_dpio_dev { int32_t hw_id; /**< An unique ID of this DPIO device instance */ uint8_t intr_enabled; /**< DQRI portal interrupt already set up */ int32_t cpu_affine; - uint16_t ethrx_intr_refcnt; /**< rx queues currently armed on this portal */ struct dpaa2_portal_dqrr dpaa2_held_bufs; }; @@ -213,7 +212,7 @@ struct __rte_cache_aligned dpaa2_queue { * its ethrx portal, arms the DQRI, and drains by channel volatile pull. */ struct dpaa2_dpcon_dev *napi_dpcon; /*!< notif channel, NULL = napi off */ - RTE_ATOMIC(struct dpaa2_dpio_dev *) napi_sub_dpio; /*!< subscribed portal or NULL */ + struct dpaa2_dpio_dev *napi_dpio; uint8_t napi_armed; /*!< this queue requests DQRI wakeups */ }; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index ad80fd51f5..01c71fc0d2 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -88,7 +88,7 @@ static __rte_always_inline struct dpaa2_dpio_dev * dpaa2_event_portal_io_prepare(struct dpaa2_port *dpaa2_portal) { struct dpaa2_dpio_dev *dpio_dev; - int ret, cpu = rte_lcore_id(); + int cpu = rte_lcore_id(); if (unlikely(!dpaa2_portal->dpio_dev)) { DPAA2_EVENTDEV_ERR("Event port%d not setup", dpaa2_portal->port_id); @@ -111,19 +111,7 @@ dpaa2_event_portal_io_prepare(struct dpaa2_port *dpaa2_portal) DPAA2_EVENTDEV_DEBUG("Event port%d affine CPU from %d->%d", dpaa2_portal->port_id, dpio_dev->cpu_affine, cpu); dpio_dev->cpu_affine = cpu; - ret = dpaa2_dpio_intr_affinity_set(dpio_dev, cpu); - if (ret) { - DPAA2_EVENTDEV_ERR("Failed(%d) to affinity dpio.%d's interrupt on core%d", - ret, dpio_dev->hw_id, cpu); - } - ret = dpaa2_dpio_cpufreq_governor(cpu, false); - if (ret) - DPAA2_EVENTDEV_WARN("Failed(%d) to set governor of core%d", ret, cpu); - ret = dpaa2_dpio_configure_stashing(dpio_dev, cpu); - if (ret) { - DPAA2_EVENTDEV_WARN("Failed(%d) to configure dpio.%d's stashing on core%d", - ret, dpio_dev->hw_id, cpu); - } + dpaa2_dpio_intr_thread_affinity(dpio_dev); } return dpio_dev; @@ -527,8 +515,14 @@ dpaa2_eventdev_port_release(void *port) } } - if (portal->dpio_dev) + if (portal->dpio_dev) { + /* + * Restore CPU-frequency governor that the optional first-touch + * binding on this DPIO may have forced. + */ + dpaa2_dpio_intr_thread_restore(portal->dpio_dev); rte_dpaa2_free_dpio_device(portal->dpio_dev); + } rte_free(portal); if (eventdev) @@ -602,15 +596,6 @@ dpaa2_eventdev_close(struct rte_eventdev *dev) dpaa2_eventdev_port_release(dev->data->ports[i]); } - /* - * Restore any CPU-frequency governor that the optional first-touch - * binding may have forced (see dpaa2_dpio_cpufreq_governor(cpu, false)). - * Best-effort and a no-op when the governor was never touched. - */ - ret = dpaa2_dpio_cpufreq_governor(-1, true); - if (ret) - DPAA2_EVENTDEV_ERR("Failed(%d) to restore all cpus' governors", ret); - ret = dpaa2_eventdev_eth_queue_del(dev, NULL, -1); if (!ret) priv->status = DPAA2_EVENTDEV_CREATED; @@ -880,7 +865,7 @@ dpaa2_eventdev_port_setup(struct rte_eventdev *dev, uint8_t port_id, } portal->dpio_dev = rte_dpaa2_alloc_dpio_device(true, - DPAA2_PORTAL_INTR_COALESC_DISABLE, -1); + DPAA2_PORTAL_INTR_COALESC_DISABLE, -1, true); if (!portal->dpio_dev) { rte_free(portal); return -ENODEV; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c91dfb7893..d8a183453b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1173,12 +1173,16 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) /* cleaning up queue storage */ for (i = 0; i < priv->nb_rx_queues; i++) { dpaa2_q = priv->rx_vq[i]; - if (dpaa2_q->napi_dpcon) { /* release the rx-intr channel */ - dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); + /* release the rx-intr channel */ + dpaa2_dev_rx_queue_intr_unbind(dpaa2_q); + if (dpaa2_q->napi_dpcon) { rte_dpaa2_free_dpcon_dev(dpaa2_q->napi_dpcon); dpaa2_q->napi_dpcon = NULL; - rte_atomic_store_explicit(&dpaa2_q->napi_sub_dpio, - NULL, rte_memory_order_release); + } + if (dpaa2_q->napi_dpio) { + dpaa2_dpio_intr_thread_restore(dpaa2_q->napi_dpio); + rte_dpaa2_free_dpio_device(dpaa2_q->napi_dpio); + dpaa2_q->napi_dpio = NULL; } dpaa2_clear_queue_active_dps(dpaa2_q, RTE_MAX_LCORE); dpaa2_queue_storage_free(dpaa2_q, RTE_MAX_LCORE); @@ -1486,11 +1490,10 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev) */ if (dev->data->dev_conf.intr_conf.rxq && dev->intr_handle == NULL) { dev->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE); - if (!dev->intr_handle || - rte_intr_vec_list_alloc(dev->intr_handle, "rxq_intr", - priv->nb_rx_queues) || - rte_intr_nb_efd_set(dev->intr_handle, priv->nb_rx_queues) || - rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_EXT)) { + if (!dev->intr_handle || rte_intr_vec_list_alloc(dev->intr_handle, "rxq_intr", + priv->nb_rx_queues) || rte_intr_nb_efd_set(dev->intr_handle, + priv->nb_rx_queues) || rte_intr_type_set(dev->intr_handle, + RTE_INTR_HANDLE_EXT)) { DPAA2_PMD_ERR("Failed to set up rx-queue interrupts"); /* capture the error before cleanup may clobber rte_errno */ ret = rte_errno ? -rte_errno : -EIO; @@ -1579,17 +1582,11 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, dpaa2_q->bp_array = rte_dpaa2_bpid_info; dpaa2_q->offloads = rx_conf->offloads; - /* NAPI: grab a DPCON channel so dev_start can bind this FQ statically. - * The DQRR burst replaces the poll path for every queue at once, so a - * missing channel is fatal rather than a silent per-queue fallback. - */ - rte_atomic_store_explicit(&dpaa2_q->napi_sub_dpio, NULL, - rte_memory_order_release); - if (dev->data->dev_conf.intr_conf.rxq && !dpaa2_q->napi_dpcon) { - dpaa2_q->napi_dpcon = rte_dpaa2_alloc_dpcon_dev(); + if (dev->data->dev_conf.intr_conf.rxq) { + if (!dpaa2_q->napi_dpcon) + dpaa2_q->napi_dpcon = rte_dpaa2_alloc_dpcon_dev(); if (!dpaa2_q->napi_dpcon) { - DPAA2_PMD_ERR("rxq %d: no DPCON for rx-queue interrupts", - rx_queue_id); + DPAA2_PMD_ERR("rxq %d: no DPCON for rx-queue interrupts", rx_queue_id); ret = -ENODEV; goto err_quit; } @@ -1600,6 +1597,27 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, DPAA2_PMD_ERR("rxq %d: dpcon_enable: %d", rx_queue_id, ret); goto err_quit; } + if (!dpaa2_q->napi_dpio) { + dpaa2_q->napi_dpio = rte_dpaa2_alloc_dpio_device(true, + DPAA2_PORTAL_INTR_COALESC_DISABLE, -1, false); + } + if (!dpaa2_q->napi_dpio) { + ret = -ENODEV; + DPAA2_PMD_ERR("rxq %d: no DPIO for rx-queue interrupts", + rx_queue_id); + goto err_quit; + } + /** Register the interrupt here; the hardware will be enabled in + * dpaa2_dev_rx_queue_intr_enable(). + */ + ret = rte_intr_vec_list_index_set(dev->intr_handle, rx_queue_id, + rx_queue_id + RTE_INTR_VEC_RXTX_OFFSET); + if (ret) + goto err_quit; + ret = rte_intr_efds_index_set(dev->intr_handle, rx_queue_id, + rte_intr_fd_get(dpaa2_q->napi_dpio->intr_handle)); + if (ret) + goto err_quit; } /*Get the flow id from given VQ id*/ @@ -1635,17 +1653,14 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, cfg->flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg->flc.value); if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { - dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, - &cfg->flc.value); + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg->flc.value); dpaa2_q->data_stashing_off = 1; } else { - dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 1, - &cfg->flc.value); + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 1, &cfg->flc.value); dpaa2_q->data_stashing_off = 0; } if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { - dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, 1, - &cfg->flc.value); + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, 1, &cfg->flc.value); } } @@ -1704,13 +1719,17 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, rte_free(dpaa2_q->cfg); dpaa2_q->cfg = NULL; } - /* free only the DPCON this call allocated; a pre-existing one belongs to - * an earlier setup and is released at dev_close + /* free only the DPCON/DPIO this call allocated; a pre-existing one + * belongs to an earlier setup and is released at dev_close. */ if (dpaa2_q->napi_dpcon) { rte_dpaa2_free_dpcon_dev(dpaa2_q->napi_dpcon); dpaa2_q->napi_dpcon = NULL; } + if (dpaa2_q->napi_dpio) { + rte_dpaa2_free_dpio_device(dpaa2_q->napi_dpio); + dpaa2_q->napi_dpio = NULL; + } return ret; } @@ -1865,14 +1884,10 @@ dpaa2_dev_rx_queue_intr_unbind(struct dpaa2_queue *dpaa2_q) /* the portal (CDAN, DQRI) can only be torn down on the polling lcore; * warn if the app skipped rte_eth_dev_rx_intr_disable() before stop/close */ - if (dpaa2_q->napi_armed) - DPAA2_PMD_WARN("rxq flow %u freed while armed; call " - "rte_eth_dev_rx_intr_disable() on the polling " - "lcore before stop/close", dpaa2_q->flow_id); - - /* CDAN and DQRI teardown is the worker's job via rte_eth_dev_rx_intr_disable() */ - rte_atomic_store_explicit(&dpaa2_q->napi_sub_dpio, NULL, - rte_memory_order_release); + if (dpaa2_q->napi_armed) { + DPAA2_PMD_WARN("rxq flow %u freed while armed; disable intr before stop", + dpaa2_q->flow_id); + } } static void @@ -3651,53 +3666,31 @@ dpaa2_napi_set_cdan_dest(struct dpaa2_queue *dpaa2_q, struct dpaa2_dpio_dev *dpi */ static int dpaa2_napi_subscribe(struct rte_eth_dev *dev, uint16_t queue_id, - struct dpaa2_dpio_dev *dpio, struct dpaa2_dpio_dev *old) + struct dpaa2_dpio_dev *dpio) { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_queue *dpaa2_q = priv->rx_vq[queue_id]; uint16_t chid = dpaa2_q->napi_dpcon->qbman_ch_id; int ret; - if (old) { - /* re-home: CDAN already off old (-EBUSY ensures it was disabled - * first); just drop the sub, never touch a foreign portal. - */ - rte_atomic_store_explicit(&dpaa2_q->napi_sub_dpio, NULL, - rte_memory_order_release); - } /* push_set ORs the channel-0 bit (idempotent across queues sharing the * portal); CDAN context = the queue, so the wake path can demux it. */ qbman_swp_push_set(dpio->sw_portal, 0, 1); /* context only; the arm path is the sole place that enables the CDAN */ - ret = qbman_swp_CDAN_set_context(dpio->sw_portal, chid, - (uint64_t)(uintptr_t)dpaa2_q); + ret = qbman_swp_CDAN_set_context(dpio->sw_portal, chid, (uint64_t)dpaa2_q); if (ret) { DPAA2_PMD_ERR("napi: CDAN set_context rxq %d: %d", queue_id, ret); return ret; } ret = dpaa2_napi_set_cdan_dest(dpaa2_q, dpio); if (ret) { - DPAA2_PMD_ERR("napi: dpcon_set_notification rxq %d: %d", - queue_id, ret); + DPAA2_PMD_ERR("napi: dpcon_set_notification rxq %d: %d", queue_id, ret); return ret; /* CDAN not enabled here -> nothing to unwind */ } DPAA2_PMD_DEBUG("napi-cdan rxq=%u dpio=%u chid=%u", queue_id, dpio->index, chid); - /* point the queue's eventfd at the portal DQRI fd for the generic epoll */ - if (rte_intr_vec_list_index_set(dev->intr_handle, queue_id, - queue_id + RTE_INTR_VEC_RXTX_OFFSET) || - rte_intr_efds_index_set(dev->intr_handle, queue_id, - rte_intr_fd_get(dpio->intr_handle))) { - DPAA2_PMD_ERR("napi: efd wiring rxq %d", queue_id); - return -EIO; - } - rte_atomic_store_explicit(&dpaa2_q->napi_sub_dpio, dpio, - rte_memory_order_release); - /* pin this portal's MSI to the worker's core: a CDAN wake then lands on - * the same core the worker sleeps on, instead of the default spread. - */ - dpaa2_dpio_affine_intr_to_core(dpio); + return 0; } @@ -3706,74 +3699,42 @@ dpaa2_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id) { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_queue *dpaa2_q = priv->rx_vq[queue_id]; - struct dpaa2_dpio_dev *dpio, *old; int ret; - /* the generic API has no dev_started guard (unlike the burst dummy ops), - * so it can reach us after a stop; do not arm a stopped port, let the - * caller fall back to polling. - */ - if (!dev->data->dev_started) - return -EIO; - if (!dpaa2_q->napi_dpcon) - return -ENOTSUP; /* no channel -> caller keeps polling */ - - if (dpaa2_affine_qbman_ethrx_swp()) - return -EIO; - dpio = DPAA2_PER_LCORE_ETHRX_DPIO; + if (dpaa2_q->napi_armed) + return 0; - old = rte_atomic_load_explicit(&dpaa2_q->napi_sub_dpio, rte_memory_order_acquire); - if (old && old != dpio && dpaa2_q->napi_armed) { - DPAA2_PMD_ERR("rxq %d still armed on another portal; disable it first", - queue_id); - return -EBUSY; - } + if (!dpaa2_q->napi_dpcon || !dpaa2_q->napi_dpio) + return -ENOTSUP; ret = dpaa2_napi_quiesce_vdq(dpaa2_q); if (ret) - return ret; + goto err_quit; - /* holdoff 0: the DQRI fires immediately on the first entry, so the - * threshold is moot (1 here). build_epoll=false: the generic rx-intr API - * waits on the application epoll, not the portal's private one. Idempotent - * per dpio. - */ - ret = dpaa2_dpio_intr_init(dpio, 1, 0, false); + ret = dpaa2_napi_subscribe(dev, queue_id, dpaa2_q->napi_dpio); if (ret) - return ret; - - if (old != dpio) { - ret = dpaa2_napi_subscribe(dev, queue_id, dpio, old); - if (ret) - return ret; - } - - /* first arm on this portal: mask + drain stale CDANs, so the unmask on - * the 0 -> 1 edge below is the sole DQRI open (independent of prior state) - */ - if (!dpaa2_q->napi_armed && dpio->ethrx_intr_refcnt == 0) { - qbman_swp_interrupt_set_inhibit(dpio->sw_portal, 1); - dpaa2_napi_drain_portal(dpio); - } + goto err_quit; /* CDAN is one-shot and the sole arming point, re-armed every sleep. * Publish armed/refcnt only on a successful initial enable. */ - ret = qbman_swp_CDAN_enable(dpio->sw_portal, dpaa2_q->napi_dpcon->qbman_ch_id); + ret = qbman_swp_CDAN_enable(dpaa2_q->napi_dpio->sw_portal, + dpaa2_q->napi_dpcon->qbman_ch_id); if (ret) { DPAA2_PMD_DEBUG("napi: CDAN arm rxq %d: %d", queue_id, ret); /* initial arm: nothing published; re-arm: state kept. Don't sleep. */ - return -EAGAIN; + ret = -EAGAIN; + goto err_quit; } - if (!dpaa2_q->napi_armed) { - dpaa2_q->napi_armed = 1; - /* unmask the portal DQRI once, on the 0 -> 1 armed-queue edge */ - if (dpio->ethrx_intr_refcnt++ == 0) - qbman_swp_interrupt_set_inhibit(dpio->sw_portal, 0); - } + qbman_swp_interrupt_set_inhibit(dpaa2_q->napi_dpio->sw_portal, 0); + + dpaa2_q->napi_armed = true; return 0; +err_quit: + + return ret; } /* Disarm rx-queue interrupts for this queue. The portal DQRI is masked only @@ -3785,38 +3746,33 @@ dpaa2_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id) { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_queue *dpaa2_q = priv->rx_vq[queue_id]; - struct dpaa2_dpio_dev *dpio; + struct dpaa2_dpio_dev *dpio = dpaa2_q->napi_dpio; uint64_t ev; ssize_t nb; - dpio = rte_atomic_load_explicit(&dpaa2_q->napi_sub_dpio, rte_memory_order_acquire); - if (dpio && dpaa2_q->napi_armed) { - dpaa2_q->napi_armed = 0; - /* Silence this queue's CDAN on the portal the worker owns. Runs on - * the polling lcore, so this is the only safe place to drive the - * single-owner software portal. It also returns the channel to the - * pool clean (CDAN disabled) and lets a sibling queue keep its own - * interrupt (per-queue, unlike the portal-wide DQRI mask below). - */ - qbman_swp_CDAN_disable(dpio->sw_portal, - dpaa2_q->napi_dpcon->qbman_ch_id); - if (dpio->ethrx_intr_refcnt > 0 && - --dpio->ethrx_intr_refcnt == 0) { - /* last queue on the shared portal: drain + clear so the next - * arm sees a clean portal (once per wake), then mask. - */ - dpaa2_napi_drain_portal(dpio); - qbman_swp_interrupt_set_inhibit(dpio->sw_portal, 1); - /* drain the VFIO eventfd: it is EPOLLET and the EAL leaves - * RTE_INTR_HANDLE_EXT undrained, so a stale count suppresses the - * next wake edge. Same as dpaa/mlx4/mlx5 do on disarm. - */ - nb = read(rte_intr_fd_get(dpio->intr_handle), &ev, sizeof(ev)); - if (nb != (ssize_t)sizeof(ev) && errno != EAGAIN) - DPAA2_PMD_DEBUG("napi: eventfd drain rxq %d (%zd)", - queue_id, nb); - } - } + if (!dpaa2_q->napi_armed || !dpio) + return 0; + + /* Silence this queue's CDAN on the portal the worker owns. Runs on + * the polling lcore, so this is the only safe place to drive the + * single-owner software portal. It also returns the channel to the + * pool clean (CDAN disabled) and lets a sibling queue keep its own + * interrupt (per-queue, unlike the portal-wide DQRI mask below). + */ + qbman_swp_CDAN_disable(dpio->sw_portal, dpaa2_q->napi_dpcon->qbman_ch_id); + /* last queue on the shared portal: drain + clear so the next + * arm sees a clean portal (once per wake), then mask. + */ + dpaa2_napi_drain_portal(dpio); + qbman_swp_interrupt_set_inhibit(dpio->sw_portal, 1); + /* drain the VFIO eventfd: it is EPOLLET and the EAL leaves + * RTE_INTR_HANDLE_EXT undrained, so a stale count suppresses the + * next wake edge. Same as dpaa/mlx4/mlx5 do on disarm. + */ + nb = read(rte_intr_fd_get(dpio->intr_handle), &ev, sizeof(ev)); + if (nb != sizeof(ev) && errno != EAGAIN) + DPAA2_PMD_DEBUG("napi: eventfd drain rxq %d (%zd)", queue_id, nb); + dpaa2_q->napi_armed = false; return 0; } diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 0df758148c..efaa862623 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -963,7 +963,7 @@ dpaa2_dev_prefetch_rx_common(struct dpaa2_queue *dpaa2_q, { /* Function receive frames for a given device and VQ*/ struct qbman_result *dq_storage, *dq_storage1 = NULL; - int ret, num_rx = 0; + int ret, num_rx = 0, cpu = rte_lcore_id(); bool by_channel = dpaa2_q->napi_dpcon ? true : false; uint32_t id, pull_size; uint8_t pending, status; @@ -971,26 +971,36 @@ dpaa2_dev_prefetch_rx_common(struct dpaa2_queue *dpaa2_q, const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; + struct dpaa2_dpio_dev *dpio; - q_storage = dpaa2_q->q_storage[rte_lcore_id()]; + q_storage = dpaa2_q->q_storage[cpu]; - if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { - ret = dpaa2_affine_qbman_ethrx_swp(); - if (ret) { - DPAA2_PMD_ERR("Failure in affining portal"); - return 0; + if (dpaa2_q->napi_dpio) { + dpio = dpaa2_q->napi_dpio; + if (unlikely(dpio->cpu_affine != cpu)) { + dpio->cpu_affine = cpu; + dpaa2_dpio_intr_thread_affinity(dpio); } + } else { + if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { + ret = dpaa2_affine_qbman_ethrx_swp(); + if (ret) { + DPAA2_PMD_ERR("Failure in affining portal"); + return 0; + } + } + dpio = DPAA2_PER_LCORE_ETHRX_DPIO; } + swp = dpio->sw_portal; - swp = DPAA2_PER_LCORE_ETHRX_PORTAL; if (dpaa2_q->napi_dpcon) id = dpaa2_q->napi_dpcon->qbman_ch_id; else id = dpaa2_q->fqid; pull_size = (nb_pkts > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_pkts; if (unlikely(!q_storage->active_dqs)) { - dpaa2_dev_rx_active_dq_storage(q_storage, DPAA2_PER_LCORE_ETHRX_DPIO, - id, pull_size, by_channel, qbman_pull_type_active); + dpaa2_dev_rx_active_dq_storage(q_storage, dpio, id, pull_size, + by_channel, qbman_pull_type_active); } dq_storage = q_storage->active_dqs; @@ -1044,11 +1054,10 @@ dpaa2_dev_prefetch_rx_common(struct dpaa2_queue *dpaa2_q, num_rx++; } while (pending); - if (check_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index)) { - while (!qbman_check_command_complete( - get_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index))) + if (check_swp_active_dqs(dpio->index)) { + while (!qbman_check_command_complete(get_swp_active_dqs(dpio->index))) ; - clear_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index); + clear_swp_active_dqs(dpio->index); } /* issue a volatile dequeue command for next pull */ while (1) { @@ -1059,8 +1068,8 @@ dpaa2_dev_prefetch_rx_common(struct dpaa2_queue *dpaa2_q, break; } q_storage->active_dqs = dq_storage1; - q_storage->active_dpio_id = DPAA2_PER_LCORE_ETHRX_DPIO->index; - set_swp_active_dqs(DPAA2_PER_LCORE_ETHRX_DPIO->index, dq_storage1); + q_storage->active_dpio_id = dpio->index; + set_swp_active_dqs(dpio->index, dq_storage1); dpaa2_q->rx_pkts += num_rx; @@ -1176,8 +1185,7 @@ dpaa2_dev_prefetch_rx(void *queue, struct rte_mbuf **bufs, if (unlikely(!rte_dpaa2_bpid_info && rte_eal_process_type() == RTE_PROC_SECONDARY)) rte_dpaa2_bpid_info = dpaa2_q->bp_array; - if (unlikely((priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) && - !dpaa2_q->napi_dpcon)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dpaa2_dev_prefetch_rx_err_pkts_dump(priv->rx_err_vq); if (likely(!(priv->psr_dynfield_offset & DPAA2_PSR_DYNFIELD_OFFSET_EN) && @@ -1265,32 +1273,31 @@ dpaa2_dev_rx_common(struct dpaa2_queue *dpaa2_q, uint32_t next_pull = nb_pkts, id, pull_size; uint16_t num_rx = 0, num_pulled; bool by_channel = dpaa2_q->napi_dpcon ? true : false; - int ret; + int ret, cpu = rte_lcore_id(); uint8_t pending, status; struct qbman_swp *swp; const struct qbman_fd *fd; struct qbman_pull_desc pulldesc; + struct dpaa2_dpio_dev *dpio; - if (by_channel) { - if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { - ret = dpaa2_affine_qbman_ethrx_swp(); - if (ret) { - DPAA2_PMD_ERR("Failure in affining portal"); - return 0; - } + if (dpaa2_q->napi_dpio) { + dpio = dpaa2_q->napi_dpio; + if (unlikely(dpio->cpu_affine != cpu)) { + dpio->cpu_affine = cpu; + dpaa2_dpio_intr_thread_affinity(dpio); } - swp = DPAA2_PER_LCORE_ETHRX_PORTAL; } else { if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_PMD_ERR("Failed to allocate IO portal, tid: %d", - rte_gettid()); + DPAA2_PMD_ERR("Failure in affining portal"); return 0; } } - swp = DPAA2_PER_LCORE_PORTAL; + dpio = DPAA2_PER_LCORE_DPIO; } + swp = dpio->sw_portal; + if (dpaa2_q->napi_dpcon) id = dpaa2_q->napi_dpcon->qbman_ch_id; else -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 53/65] net/dpaa2: add API to clean Tx confirmation queue 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (51 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 52/65] net/dpaa2: bind per-queue DPIO for rx-queue interrupts Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 54/65] event/dpaa2: fix DQRR held buffer accounting on enqueue Prashant Gupta ` (11 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> When Tx confirmation is enabled, transmitted mbufs are only released back to their pool once the corresponding Tx-confirm frames are dequeued. On a port that stops transmitting, these confirmations are never drained and the mbufs stay held. Applications had no way to force this cleanup. Add rte_pmd_dpaa2_clean_tx_conf() so an application can drain the Tx-confirm queue associated with a given port and Tx queue on demand. To support this, dpaa2_dev_tx_conf() is changed to take the tx-confirm queue directly instead of the Tx queue, and its callers are updated to pass tx_conf_queue explicitly. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 22 ++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 +- drivers/net/dpaa2/dpaa2_ptp.c | 2 +- drivers/net/dpaa2/dpaa2_rxtx.c | 22 ++++++++++------------ drivers/net/dpaa2/rte_pmd_dpaa2.h | 4 ++++ 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index d8a183453b..fe43779b10 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1240,6 +1240,28 @@ dpaa2_dev_dcb_info(struct rte_eth_dev *dev, return 0; } +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_clean_tx_conf, 26.11) +uint16_t +rte_pmd_dpaa2_clean_tx_conf(uint32_t eth_id, uint16_t txq_id) +{ + struct rte_eth_dev *dev; + struct dpaa2_queue *txq; + + if (unlikely(!rte_pmd_dpaa2_dev_is_dpaa2(eth_id))) { + DPAA2_PMD_WARN("eth%d is NOT dpaa2 device", eth_id); + return 0; + } + + dev = &rte_eth_devices[eth_id]; + txq = dev->data->tx_queues[txq_id]; + + if (txq->tx_conf_queue) + return dpaa2_dev_tx_conf(txq->tx_conf_queue, true); + + DPAA2_PMD_WARN("TX confirm not enabled on %s", dev->data->name); + return 0; +} + RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_dpaa2_dev_configure_default_action, 26.11) int rte_pmd_dpaa2_dev_configure_default_action(uint16_t port_id, diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index d1ddea7c64..2f3f5bae2a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -981,7 +981,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id, enum dpaa2_flow_dist_type type); -uint16_t dpaa2_dev_tx_conf(void *txq, int drain); +uint16_t dpaa2_dev_tx_conf(struct dpaa2_queue *tx_conf_q, int drain); void dpaa2_dev_tx_ptp_one_step_runtime(struct rte_eth_dev *dev, diff --git a/drivers/net/dpaa2/dpaa2_ptp.c b/drivers/net/dpaa2/dpaa2_ptp.c index 00f6d04c92..90de203f93 100644 --- a/drivers/net/dpaa2/dpaa2_ptp.c +++ b/drivers/net/dpaa2/dpaa2_ptp.c @@ -218,7 +218,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, rte_memory_order_relaxed); while (txq && rte_atomic_load_explicit(&txq->ts_to_cnfd, rte_memory_order_relaxed) > 0) { - dpaa2_dev_tx_conf(txq, false); + dpaa2_dev_tx_conf(txq->tx_conf_queue, false); txq = rte_atomic_load_explicit(&priv->next_txq_to_cnf, rte_memory_order_relaxed); } diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index efaa862623..4f712ec9f7 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1417,14 +1417,14 @@ dpaa2_dev_is_mbuf_from_spec_pool(struct rte_mempool *mp, } static __rte_always_inline void __rte_hot -dpaa2_dev_tx_cnf_fd_to_mbuf(struct dpaa2_queue *dpaa2_q, +dpaa2_dev_tx_cnf_fd_to_mbuf(struct dpaa2_queue *tx_conf_q, const struct qbman_fd *fd, const struct qbman_fd **fds, struct rte_mbuf **mbuf) { void *v_addr; struct dpaa2_annot_hdr *annotation; - struct dpaa2_queue *dpaa2_txq = dpaa2_q->tx_queue; - struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; + struct dpaa2_queue *dpaa2_txq = tx_conf_q->tx_queue; + struct dpaa2_dev_priv *priv = tx_conf_q->eth_data->dev_private; RTE_SET_USED(fds); @@ -1436,17 +1436,15 @@ dpaa2_dev_tx_cnf_fd_to_mbuf(struct dpaa2_queue *dpaa2_q, annotation->word2, rte_memory_order_relaxed); rte_atomic_store_explicit(&priv->next_txq_to_cnf, dpaa2_txq, rte_memory_order_relaxed); - rte_atomic_fetch_sub_explicit(&dpaa2_q->ts_to_cnfd, 1, + rte_atomic_fetch_sub_explicit(&tx_conf_q->ts_to_cnfd, 1, rte_memory_order_relaxed); dpaa2_timestamp_debug(priv, __func__, priv->tx_timestamp); } } -uint16_t dpaa2_dev_tx_conf(void *txq, int drain) +uint16_t dpaa2_dev_tx_conf(struct dpaa2_queue *tx_conf_q, int drain) { /* Function receive frames for a given device and VQ*/ - struct dpaa2_queue *dpaa2_txq = txq; - struct dpaa2_queue *dpaa2_q = dpaa2_txq->tx_conf_queue; uint16_t num_rx, total = 0, idx; int bulk_free; struct rte_mbuf *mbufs[dpaa2_dqrr_size]; @@ -1455,7 +1453,7 @@ uint16_t dpaa2_dev_tx_conf(void *txq, int drain) dpaa2_dev_prefetch_next_psr_dummy : dpaa2_dev_prefetch_next_psr; dq_again: - num_rx = dpaa2_dev_prefetch_rx_common(dpaa2_q, NULL, mbufs, dpaa2_dqrr_size, + num_rx = dpaa2_dev_prefetch_rx_common(tx_conf_q, NULL, mbufs, dpaa2_dqrr_size, dpaa2_dev_tx_cnf_fd_to_mbuf, dq_prefetch); bulk_free = true; mp = NULL; @@ -1548,7 +1546,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) hw_mp = priv->bp_list->mp; if (dpaa2_q->tx_conf_queue) - dpaa2_dev_tx_conf(dpaa2_q, false); + dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue, false); /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc); @@ -1874,10 +1872,10 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, } } for (i = 0; i < loop; i++) { - if (unlikely(dpaa2_q[i]->tx_conf_queue)) { - dpaa2_dev_tx_conf(dpaa2_q[i], false); + cnf_q = dpaa2_q[i]->tx_conf_queue; + if (unlikely(cnf_q)) { + dpaa2_dev_tx_conf(cnf_q, false); if (tstamp[i]) { - cnf_q = dpaa2_q[i]->tx_conf_queue; rte_atomic_fetch_add_explicit(&cnf_q->ts_to_cnfd, 1, rte_memory_order_relaxed); } diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2.h b/drivers/net/dpaa2/rte_pmd_dpaa2.h index 5a61a952bf..0e447cb58d 100644 --- a/drivers/net/dpaa2/rte_pmd_dpaa2.h +++ b/drivers/net/dpaa2/rte_pmd_dpaa2.h @@ -203,6 +203,10 @@ int rte_pmd_dpaa2_dev_configure_default_action(uint16_t port_id, struct rte_pmd_dpaa2_default_action_conf *def_act_conf); +__rte_experimental +uint16_t +rte_pmd_dpaa2_clean_tx_conf(uint32_t eth_id, uint16_t txq_id); + #define RTE_DPAA2_EVENT_PORT_CFG_ATOMIC RTE_BIT32(31) /** RTE_DPAA2_MIX_GROUP_FLOW has same behavio as RTE_DPAA2_FLAT_GROUP_FLOW*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 54/65] event/dpaa2: fix DQRR held buffer accounting on enqueue 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (52 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 53/65] net/dpaa2: add API to clean Tx confirmation queue Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 55/65] bus/fslmc: store dequeue dpio in mbuf seq dynfield Prashant Gupta ` (10 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> In the atomic enqueue path, the DQRR held-buffer state (dqrr_size and dqrr_held) was updated while building the enqueue descriptors, before the frames were actually enqueued to the hardware. If the subsequent qbman_swp_enqueue_multiple_desc() only accepted a subset of the frames (or none, requiring a retry), the accounting had already been cleared for frames that were never sent. This left the held-buffer bookkeeping out of sync with the DQRR entries still owned by the portal, leading to premature consumption of DQRR slots and incorrect atomic context release. Defer the held-buffer update until after each enqueue reports how many frames were accepted. The per-slot DQRR size and bitmask are recorded while preparing the descriptors and applied only for the frames that were actually enqueued. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 01c71fc0d2..127397e681 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -129,8 +129,9 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; uint16_t num_tx = 0; + uint64_t dqrr_held[MAX_TX_RING_SLOTS]; int ret; - uint8_t dqrr_index; + uint8_t dqrr_index, dqrr_size[MAX_TX_RING_SLOTS]; const struct rte_event *event; struct dpaa2_queue *dpci_txq[MAX_TX_RING_SLOTS]; struct rte_event *ev_tx[MAX_TX_RING_SLOTS]; @@ -180,13 +181,15 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], qbman_eq_desc_set_fq(&eqdesc[loop], dpci_txq[loop]->fqid); qbman_eq_desc_set_no_orp(&eqdesc[loop], 0); qbman_eq_desc_set_response(&eqdesc[loop], 0, 0); + dqrr_held[loop] = 0; + dqrr_size[loop] = 0; if (event->sched_type == RTE_SCHED_TYPE_ATOMIC && *dpaa2_seqn(event->mbuf)) { dqrr_index = *dpaa2_seqn(event->mbuf) - 1; qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); - dpio_dev->dpaa2_held_bufs.dqrr_size--; - dpio_dev->dpaa2_held_bufs.dqrr_held &= ~(1 << dqrr_index); + dqrr_size[loop] = 1; + dqrr_held[loop] = UINT64_C(1) << dqrr_index; } memset(&fd_arr[loop], 0, sizeof(struct qbman_fd)); @@ -218,6 +221,10 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], goto quit; } } else { + for (i = loop; i < (loop + ret); i++) { + dpio_dev->dpaa2_held_bufs.dqrr_size -= dqrr_size[i]; + dpio_dev->dpaa2_held_bufs.dqrr_held &= ~dqrr_held[i]; + } loop += ret; retry_count = 0; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 55/65] bus/fslmc: store dequeue dpio in mbuf seq dynfield 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (53 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 54/65] event/dpaa2: fix DQRR held buffer accounting on enqueue Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 56/65] bus/fslmc: use explicit flags for mbuf seqn encoding Prashant Gupta ` (9 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The atomic scheduling context (DQRR index) is saved in the mbuf seq dynfield at dequeue time and consumed at enqueue time. However, the enqueue and dequeue may happen on different DPIO portals, so the context must remember which DPIO produced it. Change the seqn dynfield from a bare uint32_t to a small struct that carries both the sequence value and the originating dequeue DPIO pointer. This is the base type change; additional changes are in the following patches. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/bus_fslmc_driver.h | 28 +++++++++++++++++++++------- drivers/bus/fslmc/fslmc_bus.c | 4 ++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/bus/fslmc/bus_fslmc_driver.h b/drivers/bus/fslmc/bus_fslmc_driver.h index 40c9ba0699..ddde52d89c 100644 --- a/drivers/bus/fslmc/bus_fslmc_driver.h +++ b/drivers/bus/fslmc/bus_fslmc_driver.h @@ -43,21 +43,35 @@ struct vfio_device_info; #define DPAA2_INVALID_MBUF_SEQN 0 -typedef uint32_t dpaa2_seqn_t; +struct dpaa2_seq_t { + uint32_t seqn; + void *seq_dpio_dq; +}; + extern int dpaa2_seqn_dynfield_offset; /** - * Read dpaa2 sequence number from mbuf. + * Read dpaa2 sequence struct from mbuf. * * @param mbuf Structure to read from. - * @return pointer to dpaa2 sequence number. + * @return pointer to dpaa2 sequence struct. */ -__rte_internal -static inline dpaa2_seqn_t * +static __rte_always_inline struct dpaa2_seq_t * +dpaa2_seq(struct rte_mbuf *mbuf) +{ + return RTE_MBUF_DYNFIELD(mbuf, dpaa2_seqn_dynfield_offset, struct dpaa2_seq_t *); +} + +static __rte_always_inline uint32_t * dpaa2_seqn(struct rte_mbuf *mbuf) { - return RTE_MBUF_DYNFIELD(mbuf, dpaa2_seqn_dynfield_offset, - dpaa2_seqn_t *); + return &(dpaa2_seq(mbuf)->seqn); +} + +static __rte_always_inline void ** +dpaa2_seq_dpio_dq(struct rte_mbuf *mbuf) +{ + return &(dpaa2_seq(mbuf)->seq_dpio_dq); } /** Device driver supports link state interrupt */ diff --git a/drivers/bus/fslmc/fslmc_bus.c b/drivers/bus/fslmc/fslmc_bus.c index d20103ee36..82b11176e1 100644 --- a/drivers/bus/fslmc/fslmc_bus.c +++ b/drivers/bus/fslmc/fslmc_bus.c @@ -651,8 +651,8 @@ rte_fslmc_probe(struct rte_bus *bus) { static const struct rte_mbuf_dynfield dpaa2_seqn_dynfield_desc = { .name = DPAA2_SEQN_DYNFIELD_NAME, - .size = sizeof(dpaa2_seqn_t), - .align = alignof(dpaa2_seqn_t), + .size = sizeof(struct dpaa2_seq_t), + .align = alignof(struct dpaa2_seq_t), }; int ret; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 56/65] bus/fslmc: use explicit flags for mbuf seqn encoding 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (54 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 55/65] bus/fslmc: store dequeue dpio in mbuf seq dynfield Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 57/65] net/dpaa2: unify tx burst path for ordered and atomic enqueue Prashant Gupta ` (8 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 drivers stash the DQRR index in the mbuf dynamic seqn field to support atomic (DCA) and ordered (ORP) enqueue. The index was stored as "dqrr_index + 1" and the field was tested for a non-zero value to decide whether it was valid, with the index recovered as "seqn - 1". This offset-by-one scheme overloads a single field and cannot distinguish the DCA case from the ORP case; it only works because any valid index becomes non-zero. It is fragile and makes the DCA and ORP paths ambiguous. Encode the seqn using the explicit qbman flag bits instead: - store the index as "dqrr_index | QBMAN_ENQUEUE_FLAG_DCA" - recover the index with "& QBMAN_EQCR_DCA_IDXMASK" - gate the DCA path on "& QBMAN_ENQUEUE_FLAG_DCA" - gate the ORP path on "& DPAA2_ENQUEUE_FLAG_ORP" Apply this consistently across net/dpaa2, crypto/dpaa2_sec and event/dpaa2 so the atomic and ordered enqueue paths are selected unambiguously. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 17 +++++++---------- drivers/event/dpaa2/dpaa2_eventdev.c | 6 +++--- drivers/net/dpaa2/dpaa2_rxtx.c | 8 ++++---- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index e34ca884fe..54881bc38c 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1549,13 +1549,10 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, dpaa2_eqcr_size : nb_ops; for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn((*ops)->sym->m_src)) { - if (*dpaa2_seqn((*ops)->sym->m_src) & QBMAN_ENQUEUE_FLAG_DCA) { - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << - *dpaa2_seqn((*ops)->sym->m_src) & - QBMAN_EQCR_DCA_IDXMASK); - } + if (*dpaa2_seqn((*ops)->sym->m_src) & QBMAN_ENQUEUE_FLAG_DCA) { + DPAA2_PER_LCORE_DQRR_SIZE--; + DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << + *dpaa2_seqn((*ops)->sym->m_src) & QBMAN_EQCR_DCA_IDXMASK); flags[loop] = *dpaa2_seqn((*ops)->sym->m_src); *dpaa2_seqn((*ops)->sym->m_src) = DPAA2_INVALID_MBUF_SEQN; } @@ -1848,7 +1845,7 @@ dpaa2_sec_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0); } } else { - dq_idx = *dpaa2_seqn(m) - 1; + dq_idx = *dpaa2_seqn(m) & QBMAN_EQCR_DCA_IDXMASK; qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0); DPAA2_PER_LCORE_DQRR_SIZE--; DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dq_idx); @@ -1897,7 +1894,7 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, dpaa2_eqcr_size : nb_ops; if (!priv->en_loose_ordered) { - if (*dpaa2_seqn((*ops)->sym->m_src)) { + if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) { num_free_eq_desc = dpaa2_free_eq_descriptors(); if (num_free_eq_desc < frames_to_send) frames_to_send = num_free_eq_desc; @@ -1909,7 +1906,7 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, qbman_eq_desc_clear(&eqdesc[loop]); qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_qp->tx_vq.fqid); - if (*dpaa2_seqn((*ops)->sym->m_src)) + if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) dpaa2_sec_set_enqueue_descriptor( &dpaa2_qp->tx_vq, (*ops)->sym->m_src, diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 127397e681..2efdbb8b59 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -185,8 +185,8 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], dqrr_size[loop] = 0; if (event->sched_type == RTE_SCHED_TYPE_ATOMIC && - *dpaa2_seqn(event->mbuf)) { - dqrr_index = *dpaa2_seqn(event->mbuf) - 1; + (*dpaa2_seqn(event->mbuf) & QBMAN_ENQUEUE_FLAG_DCA)) { + dqrr_index = *dpaa2_seqn(event->mbuf) & QBMAN_EQCR_DCA_IDXMASK; qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); dqrr_size[loop] = 1; dqrr_held[loop] = UINT64_C(1) << dqrr_index; @@ -273,7 +273,7 @@ static void dpaa2_eventdev_process_atomic(struct dpaa2_dpio_dev *dpio_dev, rte_memcpy(ev, rx_ev, sizeof(struct rte_event)); rte_mempool_put(rxq->env_pool, rx_ev); - *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; + *dpaa2_seqn(ev->mbuf) = dqrr_index | QBMAN_ENQUEUE_FLAG_DCA; dpio_dev->dpaa2_held_bufs.dqrr_size++; dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = ev->mbuf; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 4f712ec9f7..dfd359d0e2 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1234,7 +1234,7 @@ dpaa2_dev_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); - *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; + *dpaa2_seqn(ev->mbuf) = dqrr_index | QBMAN_ENQUEUE_FLAG_DCA; dpio_dev->dpaa2_held_bufs.dqrr_size++; dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = ev->mbuf; @@ -1570,8 +1570,8 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn(*bufs)) { - uint8_t dqrr_index = *dpaa2_seqn(*bufs) - 1; + if (*dpaa2_seqn(*bufs) & QBMAN_ENQUEUE_FLAG_DCA) { + uint8_t dqrr_index = *dpaa2_seqn(*bufs) & QBMAN_EQCR_DCA_IDXMASK; flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; DPAA2_PER_LCORE_DQRR_SIZE--; @@ -1743,7 +1743,7 @@ dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0); } } else { - dq_idx = *dpaa2_seqn(m) - 1; + dq_idx = *dpaa2_seqn(m) & QBMAN_EQCR_DCA_IDXMASK; qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0); DPAA2_PER_LCORE_DQRR_SIZE--; DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dq_idx); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 57/65] net/dpaa2: unify tx burst path for ordered and atomic enqueue 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (55 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 56/65] bus/fslmc: use explicit flags for mbuf seqn encoding Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 58/65] crypto/dpaa2_sec: unify enqueue burst path for ordered enqueue Prashant Gupta ` (7 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The ordered transmit path used a dedicated burst function, dpaa2_dev_tx_ordered(), which was installed as dev->tx_pkt_burst at device start when ordered queues were enabled. This split the TX datapath into two separate entry points and required swapping the burst function and reporting a distinct "Ordered" burst mode. Make dpaa2_dev_tx() the single TX entry point. It now inspects the mbuf seqn flags (DPAA2_ENQUEUE_FLAG_ORP / QBMAN_ENQUEUE_FLAG_DCA) and, when a packet requires ordered or atomic (DCA) enqueue, routes the remaining burst through the ordered multi-queue path. dpaa2_dev_tx_ordered() is reduced to a static helper that wraps dpaa2_dev_tx_multi_txq_ordered(), and the start-time tx_pkt_burst swap, the "Ordered" burst-mode string and the exported prototype are removed. Simplify the dpaa2_dev_tx() error handling by replacing the duplicated send_n_return path with a single break and shared enqueue tail, passing NULL flags since DCA is handled on the ordered path. Rework dpaa2_dev_tx_multi_txq_ordered() to index the burst with bufs[loop] instead of advancing the buffer pointer, handle atomic (DCA) descriptors with per-slot dqrr_held/dqrr_size/flags, update per-queue tx_pkts counters, and restore the mbuf seqn flags when enqueue fails so packets can be retried. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 6 -- drivers/net/dpaa2/dpaa2_ethdev.h | 3 +- drivers/net/dpaa2/dpaa2_rxtx.c | 178 ++++++++++++++----------------- 3 files changed, 84 insertions(+), 103 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index fe43779b10..85c93bf422 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1003,8 +1003,6 @@ dpaa2_dev_tx_burst_mode_get(struct rte_eth_dev *dev, if (pkt_burst == dpaa2_dev_tx) snprintf(mode->info, sizeof(mode->info), "%s", "Scalar"); - else if (pkt_burst == dpaa2_dev_tx_ordered) - snprintf(mode->info, sizeof(mode->info), "%s", "Ordered"); else if (pkt_burst == rte_eth_pkt_burst_dummy) snprintf(mode->info, sizeof(mode->info), "%s", "Dummy"); else @@ -2343,10 +2341,6 @@ dpaa2_dev_start(struct rte_eth_dev *dev) */ dpaa2_dev_set_link_up(dev); - /* Change the tx burst function if ordered queues are used */ - if (priv->en_ordered) - dev->tx_pkt_burst = dpaa2_dev_tx_ordered; - for (i = 0; i < dev->data->nb_rx_queues; i++) dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED; for (i = 0; i < dev->data->nb_tx_queues; i++) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 2f3f5bae2a..caf3fabee7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -972,8 +972,7 @@ void dpaa2_dev_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, struct dpaa2_queue *rxq, struct rte_event *ev); uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts); -uint16_t dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, - uint16_t nb_pkts); + __rte_internal uint16_t dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, struct rte_mbuf **bufs, uint16_t nb_pkts); diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index dfd359d0e2..56da29a927 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1505,6 +1505,20 @@ dpaa2_dev_tx_fast_mbuf_to_fd(struct dpaa2_dev_priv *priv, return -EAGAIN; } +/* Callback to handle sending ordered packets through WRIOP based interface */ +static uint16_t +dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, + uint16_t nb_pkts) +{ + uint16_t i; + struct dpaa2_queue *mq[nb_pkts]; + + for (i = 0; i < nb_pkts; i++) + mq[i] = queue; + + return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); +} + /* * Callback to handle sending packets through WRIOP based interface */ @@ -1512,18 +1526,16 @@ uint16_t dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ - uint32_t loop, retry_count, i; - int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; + uint32_t loop, retry_count, i, ptp_n, frames_to_send; + int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set, order = false, eq_ret = 0; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - uint32_t frames_to_send; struct qbman_eq_desc eqdesc; struct dpaa2_queue *dpaa2_q = queue; struct qbman_swp *swp; - uint16_t num_tx = 0; + uint16_t num_tx = 0, order_tx; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; struct rte_mempool *hw_mp; - uint32_t flags[MAX_TX_RING_SLOTS] = {0}; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -1558,7 +1570,7 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) tx_again: /*Check if the queue is congested*/ retry_count = 0; - ptp_set_count = 0; + ptp_n = 0; while (qbman_result_SCN_state(dpaa2_q->cscn)) { retry_count++; /* Retry for some time before giving up */ @@ -1566,24 +1578,19 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) goto skip_tx; } - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn(*bufs) & QBMAN_ENQUEUE_FLAG_DCA) { - uint8_t dqrr_index = *dpaa2_seqn(*bufs) & QBMAN_EQCR_DCA_IDXMASK; - - flags[loop] = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); - *dpaa2_seqn(*bufs) = DPAA2_INVALID_MBUF_SEQN; + if (unlikely(*dpaa2_seqn((*bufs)) & + (DPAA2_ENQUEUE_FLAG_ORP | QBMAN_ENQUEUE_FLAG_DCA))) { + order = true; + break; } - if (unlikely((*bufs)->ol_flags - & RTE_MBUF_F_TX_VLAN)) { + if (unlikely((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN)) { ret = rte_vlan_insert(bufs); if (ret) - goto send_n_return; + break; } tstamp[loop] = false; @@ -1593,8 +1600,8 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, &tstamp[loop], &ptp_set); if (ptp_set) - ptp_set_count++; - if (ptp_set_count > 1) + ptp_n++; + if (ptp_n > 1) DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); goto skip_fast_mbuf2fd; } @@ -1614,25 +1621,22 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) dpaa2_q, priv->tx_conf_type, tstamp[loop]); } if (ret) - goto send_n_return; + break; bufs++; } + frames_to_send = loop; loop = 0; retry_count = 0; while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], &flags[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { + eq_ret = qbman_swp_enqueue_multiple(swp, &eqdesc, + &fd_arr[loop], NULL, frames_to_send - loop); + if (unlikely(eq_ret < 0)) { retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_pkts -= loop; - goto send_n_return; - } + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + break; } else { - loop += ret; + loop += eq_ret; retry_count = 0; } } @@ -1647,42 +1651,21 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } } } - if (nb_pkts > 0) + if (nb_pkts > 0 && !ret && !order) goto tx_again; - dpaa2_q->tx_pkts += num_tx; - - return num_tx; - -send_n_return: - /* send any already prepared fd */ - retry_count = 0; - i = 0; - while (i < loop) { - ret = qbman_swp_enqueue_multiple(swp, &eqdesc, &fd_arr[i], - &flags[i], loop - i); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - i += ret; - retry_count = 0; - } - } - num_tx += i; - if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { - loop = i; - for (i = 0; i < loop; i++) { - if (tstamp[i]) { - rte_atomic_fetch_add_explicit(&dpaa2_q->tx_conf_queue->ts_to_cnfd, - 1, rte_memory_order_relaxed); - } - } - } - skip_tx: dpaa2_q->tx_pkts += num_tx; + if (order && eq_ret >= 0) { +order_tx_again: + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; + nb_pkts -= frames_to_send; + order_tx = dpaa2_dev_tx_ordered(queue, bufs, frames_to_send); + num_tx += order_tx; + bufs += frames_to_send; + if (nb_pkts && order_tx >= frames_to_send) + goto order_tx_again; + } return num_tx; } @@ -1758,7 +1741,7 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, { /* Function to transmit the frames to multiple queues respectively.*/ uint32_t loop, retry_count, i; - int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_set_count, ptp_set; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_n, ptp_set; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; struct rte_mempool *hw_mp; @@ -1767,6 +1750,9 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, struct dpaa2_dev_priv *priv; struct dpaa2_queue *order_sendq; struct dpaa2_queue *cnf_q; + uint8_t dqrr_size[MAX_TX_RING_SLOTS], dqrr_index; + uint64_t dqrr_held[MAX_TX_RING_SLOTS]; + uint32_t flags[MAX_TX_RING_SLOTS]; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -1778,14 +1764,14 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, } swp = DPAA2_PER_LCORE_PORTAL; - ptp_set_count = 0; + ptp_n = 0; frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { priv = dpaa2_q[loop]->eth_data->dev_private; if (!priv->en_loose_ordered && - (*dpaa2_seqn(*bufs) & DPAA2_ENQUEUE_FLAG_ORP)) { + (*dpaa2_seqn(bufs[loop]) & DPAA2_ENQUEUE_FLAG_ORP)) { if (!num_free_eq_desc) { num_free_eq_desc = dpaa2_free_eq_descriptors(); if (!num_free_eq_desc) { @@ -1810,32 +1796,41 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); - if (*dpaa2_seqn(*bufs) && priv->en_ordered) { + dqrr_held[loop] = 0; + dqrr_size[loop] = 0; + if ((*dpaa2_seqn(bufs[loop]) & DPAA2_ENQUEUE_FLAG_ORP) && + priv->en_ordered) { order_sendq = priv->tx_vq[0]; - dpaa2_set_enqueue_descriptor(order_sendq, *bufs, &eqdesc[loop]); + dpaa2_set_enqueue_descriptor(order_sendq, bufs[loop], &eqdesc[loop]); } else { qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); + if (*dpaa2_seqn(bufs[loop]) & QBMAN_ENQUEUE_FLAG_DCA) { + dqrr_index = *dpaa2_seqn(bufs[loop]) & QBMAN_EQCR_DCA_IDXMASK; + dqrr_held[loop] = ~(UINT64_C(1) << dqrr_index); + dqrr_size[loop] = 1; + flags[loop] = *dpaa2_seqn(bufs[loop]); + *dpaa2_seqn(bufs[loop]) = DPAA2_INVALID_MBUF_SEQN; + qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); + } } tstamp[loop] = false; - if (unlikely(((*bufs)->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && + if (unlikely((bufs[loop]->ol_flags & RTE_MBUF_F_TX_IEEE1588_TMST) && (priv->flags & DPAA2_IEEE1588_TX_TS_FLAG))) { ptp_set = false; - dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, *bufs, + dpaa2_dev_tx_ptp_one_step_runtime(priv->eth_dev, bufs[loop], &tstamp[loop], &ptp_set); if (ptp_set) - ptp_set_count++; - if (ptp_set_count > 1) + ptp_n++; + if (ptp_n > 1) DPAA2_PMD_WARN("Multiple ptp formats in burst transmission!"); goto skip_fast_mbuf2fd; } - ret = dpaa2_dev_tx_fast_mbuf_to_fd(priv, *bufs, &fd_arr[loop]); - if (likely(!ret)) { - bufs++; + ret = dpaa2_dev_tx_fast_mbuf_to_fd(priv, bufs[loop], &fd_arr[loop]); + if (likely(!ret)) continue; - } skip_fast_mbuf2fd: if (unlikely(!priv->bp_list)) { @@ -1843,16 +1838,15 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, goto send_frames; } hw_mp = priv->bp_list->mp; - if (unlikely((*bufs)->nb_segs > 1)) { - ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + if (unlikely(bufs[loop]->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, bufs[loop], &fd_arr[loop], dpaa2_q[loop], priv->tx_conf_type, tstamp[loop]); } else { - ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, bufs[loop], &fd_arr[loop], dpaa2_q[loop], priv->tx_conf_type, tstamp[loop]); } if (ret) goto send_frames; - bufs++; } send_frames: @@ -1863,12 +1857,20 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, ret = qbman_swp_enqueue_multiple_desc(swp, &eqdesc[loop], &fd_arr[loop], frames_to_send - loop); if (likely(ret > 0)) { + for (i = loop; i < (loop + ret); i++) { + DPAA2_PER_LCORE_DQRR_SIZE -= dqrr_size[i]; + DPAA2_PER_LCORE_DQRR_HELD &= ~dqrr_held[i]; + dpaa2_q[i]->tx_pkts++; + } loop += ret; retry_count = 0; } else { retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { + for (i = loop; i < frames_to_send; i++) + *dpaa2_seqn(bufs[i]) = flags[i]; break; + } } } for (i = 0; i < loop; i++) { @@ -1908,20 +1910,6 @@ rte_dpaa2_dev_tx_multi_ports(uint16_t port_id[], return dpaa2_dev_tx_multi_txq_ordered(txq, bufs, nb_pkts); } -/* Callback to handle sending ordered packets through WRIOP based interface */ -uint16_t -dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, - uint16_t nb_pkts) -{ - uint16_t i; - struct dpaa2_queue *mq[nb_pkts]; - - for (i = 0; i < nb_pkts; i++) - mq[i] = queue; - - return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); -} - /* This function loopbacks all the received packets.*/ uint16_t dpaa2_dev_loopback_rx(void *queue, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 58/65] crypto/dpaa2_sec: unify enqueue burst path for ordered enqueue 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (56 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 57/65] net/dpaa2: unify tx burst path for ordered and atomic enqueue Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 59/65] bus/fslmc: track atomic DCA context per dequeue dpio Prashant Gupta ` (6 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The ordered enqueue path used a dedicated burst function, dpaa2_sec_enqueue_burst_ordered(), which was installed as dev->enqueue_burst at device start when ordered queues were enabled. This split the crypto enqueue datapath into two separate entry points and required swapping the burst function at start time. Make dpaa2_sec_enqueue_burst() the single enqueue entry point. It now inspects the mbuf seqn flags (DPAA2_ENQUEUE_FLAG_ORP / QBMAN_ENQUEUE_FLAG_DCA) and, when an op requires ordered or atomic (DCA) enqueue, routes the remaining burst through dpaa2_sec_enqueue_burst_ordered(). The start-time enqueue_burst swap is removed. Move dpaa2_sec_set_enqueue_descriptor() and dpaa2_sec_enqueue_burst_ordered() above the fast enqueue path so the single entry point can call them. The normal path no longer handles DCA flags inline and passes NULL flags to qbman_swp_enqueue_multiple(), since DCA and ORP handling now live on the ordered path. This mirrors the equivalent unification done for the net/dpaa2 tx burst path. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 362 ++++++++++---------- 1 file changed, 175 insertions(+), 187 deletions(-) diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 54881bc38c..9d2fa57989 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1502,22 +1502,174 @@ build_sec_fd(struct rte_crypto_op *op, return ret; } +static void +dpaa2_sec_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, + struct rte_mbuf *m, struct qbman_eq_desc *eqdesc) +{ + struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; + struct eqresp_metadata *eqresp_meta; + struct dpaa2_sec_dev_private *priv = dpaa2_q->crypto_data->dev_private; + uint16_t orpid, seqnum; + uint8_t dq_idx; + + if (*dpaa2_seqn(m) & DPAA2_ENQUEUE_FLAG_ORP) { + orpid = (*dpaa2_seqn(m) & DPAA2_EQCR_OPRID_MASK) >> + DPAA2_EQCR_OPRID_SHIFT; + seqnum = (*dpaa2_seqn(m) & DPAA2_EQCR_SEQNUM_MASK) >> + DPAA2_EQCR_SEQNUM_SHIFT; + + if (!priv->en_loose_ordered) { + qbman_eq_desc_set_orp(eqdesc, 1, orpid, seqnum, 0); + qbman_eq_desc_set_response(eqdesc, (uint64_t) + DPAA2_VADDR_TO_IOVA(&dpio_dev->eqresp[ + dpio_dev->eqresp_pi]), 1); + qbman_eq_desc_set_token(eqdesc, 1); + + eqresp_meta = &dpio_dev->eqresp_meta[dpio_dev->eqresp_pi]; + eqresp_meta->dpaa2_q = dpaa2_q; + eqresp_meta->mp = m->pool; + + dpio_dev->eqresp_pi + 1 < MAX_EQ_RESP_ENTRIES ? + dpio_dev->eqresp_pi++ : (dpio_dev->eqresp_pi = 0); + } else { + qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0); + } + } else { + dq_idx = *dpaa2_seqn(m) & QBMAN_EQCR_DCA_IDXMASK; + qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0); + DPAA2_PER_LCORE_DQRR_SIZE--; + DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dq_idx); + } + *dpaa2_seqn(m) = DPAA2_INVALID_MBUF_SEQN; +} + static uint16_t -dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, - uint16_t nb_ops) +dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, + uint16_t nb_ops) { /* Function to transmit the frames to given device and VQ*/ - uint32_t loop; int32_t ret; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - uint32_t frames_to_send, retry_count; + uint32_t frames_to_send, num_free_eq_desc, retry_count, loop; + struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; + struct dpaa2_sec_qp *dpaa2_qp = qp; + struct qbman_swp *swp; + uint16_t num_tx = 0, bpid; + uint8_t dqrr_index; + struct dpaa2_sec_dev_private *priv = dpaa2_qp->tx_vq.crypto_data->dev_private; + + if (unlikely(!nb_ops)) + return 0; + + if (ops[0]->sess_type == RTE_CRYPTO_OP_SESSIONLESS) { + DPAA2_SEC_ERR("sessionless crypto op not supported"); + return 0; + } + + if (!DPAA2_PER_LCORE_DPIO) { + ret = dpaa2_affine_qbman_swp(); + if (ret) { + DPAA2_SEC_ERR("Failure in affining portal"); + return 0; + } + } + swp = DPAA2_PER_LCORE_PORTAL; + + while (nb_ops) { + frames_to_send = (nb_ops > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_ops; + + if (!priv->en_loose_ordered) { + if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) { + num_free_eq_desc = dpaa2_free_eq_descriptors(); + if (num_free_eq_desc < frames_to_send) + frames_to_send = num_free_eq_desc; + } + } + + for (loop = 0; loop < frames_to_send; loop++) { + /*Prepare enqueue descriptor*/ + qbman_eq_desc_clear(&eqdesc[loop]); + qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_qp->tx_vq.fqid); + + if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) { + dpaa2_sec_set_enqueue_descriptor(&dpaa2_qp->tx_vq, + (*ops)->sym->m_src, &eqdesc[loop]); + } else { + if (*dpaa2_seqn((*ops)->sym->m_src) & QBMAN_ENQUEUE_FLAG_DCA) { + dqrr_index = *dpaa2_seqn((*ops)->sym->m_src) & + QBMAN_EQCR_DCA_IDXMASK; + DPAA2_PER_LCORE_DQRR_SIZE--; + DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); + qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); + *dpaa2_seqn((*ops)->sym->m_src) = DPAA2_INVALID_MBUF_SEQN; + } + qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); + } + + /*Clear the unused FD fields before sending*/ + memset(&fd_arr[loop], 0, sizeof(struct qbman_fd)); + if ((*ops)->sym->m_src->pool->ops_index == rte_dpaa2_mpool_get_ops_idx()) + bpid = mempool_to_bpid((*ops)->sym->m_src->pool); + else + bpid = MAX_BPID; + ret = build_sec_fd(*ops, &fd_arr[loop], bpid, dpaa2_qp); + if (ret) { + DPAA2_SEC_DP_DEBUG("FD build failed"); + frames_to_send = loop + 1; + for (loop = 0; loop < frames_to_send; loop++) + free_fle(&fd_arr[loop], dpaa2_qp); + goto skip_tx; + } + ops++; + } + + loop = 0; + retry_count = 0; + while (loop < frames_to_send) { + ret = qbman_swp_enqueue_multiple_desc(swp, + &eqdesc[loop], &fd_arr[loop], + frames_to_send - loop); + if (unlikely(ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { + num_tx += loop; + nb_ops -= loop; + DPAA2_SEC_DP_DEBUG("Enqueue fail"); + /* freeing the fle buffers */ + while (loop < frames_to_send) { + free_fle(&fd_arr[loop], dpaa2_qp); + loop++; + } + goto skip_tx; + } + } else { + loop += ret; + retry_count = 0; + } + } + + num_tx += loop; + nb_ops -= loop; + } + +skip_tx: + dpaa2_qp->tx_vq.tx_pkts += num_tx; + dpaa2_qp->tx_vq.err_pkts += nb_ops; + return num_tx; +} + +static uint16_t +dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, + uint16_t nb_ops) +{ + /* Function to transmit the frames to given device and VQ*/ + int32_t ret, order = false; + struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; struct qbman_eq_desc eqdesc; - struct dpaa2_sec_qp *dpaa2_qp = (struct dpaa2_sec_qp *)qp; + struct dpaa2_sec_qp *dpaa2_qp = qp; struct qbman_swp *swp; - uint16_t num_tx = 0; - uint32_t flags[MAX_TX_RING_SLOTS] = {0}; /*todo - need to support multiple buffer pools */ - uint16_t bpid; + uint16_t num_tx = 0, bpid, loop, frames_to_send, retry_count; struct rte_mempool *mb_pool; if (unlikely(nb_ops == 0)) @@ -1536,32 +1688,26 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, if (!DPAA2_PER_LCORE_DPIO) { ret = dpaa2_affine_qbman_swp(); if (ret) { - DPAA2_SEC_ERR( - "Failed to allocate IO portal, tid: %d", - rte_gettid()); + DPAA2_SEC_ERR("Failed to allocate IO portal, tid: %d", rte_gettid()); return 0; } } swp = DPAA2_PER_LCORE_PORTAL; while (nb_ops) { - frames_to_send = (nb_ops > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_ops; + frames_to_send = (nb_ops > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_ops; for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn((*ops)->sym->m_src) & QBMAN_ENQUEUE_FLAG_DCA) { - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << - *dpaa2_seqn((*ops)->sym->m_src) & QBMAN_EQCR_DCA_IDXMASK); - flags[loop] = *dpaa2_seqn((*ops)->sym->m_src); - *dpaa2_seqn((*ops)->sym->m_src) = DPAA2_INVALID_MBUF_SEQN; + if (*dpaa2_seqn((*ops)->sym->m_src) & + (QBMAN_ENQUEUE_FLAG_DCA | DPAA2_ENQUEUE_FLAG_ORP)) { + order = true; + break; } /*Clear the unused FD fields before sending*/ memset(&fd_arr[loop], 0, sizeof(struct qbman_fd)); mb_pool = (*ops)->sym->m_src->pool; - if (mb_pool->ops_index == - rte_dpaa2_mpool_get_ops_idx()) + if (mb_pool->ops_index == rte_dpaa2_mpool_get_ops_idx()) bpid = mempool_to_bpid(mb_pool); else bpid = MAX_BPID; @@ -1573,13 +1719,12 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, ops++; } + frames_to_send = loop; loop = 0; retry_count = 0; while (loop < frames_to_send) { ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], - &flags[loop], - frames_to_send - loop); + &fd_arr[loop], NULL, frames_to_send - loop); if (unlikely(ret < 0)) { retry_count++; if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { @@ -1588,8 +1733,7 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, DPAA2_SEC_DP_DEBUG("Enqueue fail"); /* freeing the fle buffers */ while (loop < frames_to_send) { - free_fle(&fd_arr[loop], - dpaa2_qp); + free_fle(&fd_arr[loop], dpaa2_qp); loop++; } goto skip_tx; @@ -1602,10 +1746,15 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, num_tx += loop; nb_ops -= loop; + if (order) + break; } skip_tx: dpaa2_qp->tx_vq.tx_pkts += num_tx; dpaa2_qp->tx_vq.err_pkts += nb_ops; + if (ret >= 0 && order) + num_tx += dpaa2_sec_enqueue_burst_ordered(qp, ops, nb_ops); + return num_tx; } @@ -1810,163 +1959,6 @@ dpaa2_sec_free_eqresp_buf(uint16_t eqresp_ci, rte_pktmbuf_free(op->sym->m_src); } -static void -dpaa2_sec_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, - struct rte_mbuf *m, - struct qbman_eq_desc *eqdesc) -{ - struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; - struct eqresp_metadata *eqresp_meta; - struct dpaa2_sec_dev_private *priv = dpaa2_q->crypto_data->dev_private; - uint16_t orpid, seqnum; - uint8_t dq_idx; - - if (*dpaa2_seqn(m) & DPAA2_ENQUEUE_FLAG_ORP) { - orpid = (*dpaa2_seqn(m) & DPAA2_EQCR_OPRID_MASK) >> - DPAA2_EQCR_OPRID_SHIFT; - seqnum = (*dpaa2_seqn(m) & DPAA2_EQCR_SEQNUM_MASK) >> - DPAA2_EQCR_SEQNUM_SHIFT; - - - if (!priv->en_loose_ordered) { - qbman_eq_desc_set_orp(eqdesc, 1, orpid, seqnum, 0); - qbman_eq_desc_set_response(eqdesc, (uint64_t) - DPAA2_VADDR_TO_IOVA(&dpio_dev->eqresp[ - dpio_dev->eqresp_pi]), 1); - qbman_eq_desc_set_token(eqdesc, 1); - - eqresp_meta = &dpio_dev->eqresp_meta[dpio_dev->eqresp_pi]; - eqresp_meta->dpaa2_q = dpaa2_q; - eqresp_meta->mp = m->pool; - - dpio_dev->eqresp_pi + 1 < MAX_EQ_RESP_ENTRIES ? - dpio_dev->eqresp_pi++ : (dpio_dev->eqresp_pi = 0); - } else { - qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0); - } - } else { - dq_idx = *dpaa2_seqn(m) & QBMAN_EQCR_DCA_IDXMASK; - qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0); - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dq_idx); - } - *dpaa2_seqn(m) = DPAA2_INVALID_MBUF_SEQN; -} - - -static uint16_t -dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, - uint16_t nb_ops) -{ - /* Function to transmit the frames to given device and VQ*/ - uint32_t loop; - int32_t ret; - struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - uint32_t frames_to_send, num_free_eq_desc, retry_count; - struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; - struct dpaa2_sec_qp *dpaa2_qp = (struct dpaa2_sec_qp *)qp; - struct qbman_swp *swp; - uint16_t num_tx = 0; - uint16_t bpid; - struct rte_mempool *mb_pool; - struct dpaa2_sec_dev_private *priv = - dpaa2_qp->tx_vq.crypto_data->dev_private; - - if (unlikely(nb_ops == 0)) - return 0; - - if (ops[0]->sess_type == RTE_CRYPTO_OP_SESSIONLESS) { - DPAA2_SEC_ERR("sessionless crypto op not supported"); - return 0; - } - - if (!DPAA2_PER_LCORE_DPIO) { - ret = dpaa2_affine_qbman_swp(); - if (ret) { - DPAA2_SEC_ERR("Failure in affining portal"); - return 0; - } - } - swp = DPAA2_PER_LCORE_PORTAL; - - while (nb_ops) { - frames_to_send = (nb_ops > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_ops; - - if (!priv->en_loose_ordered) { - if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (num_free_eq_desc < frames_to_send) - frames_to_send = num_free_eq_desc; - } - } - - for (loop = 0; loop < frames_to_send; loop++) { - /*Prepare enqueue descriptor*/ - qbman_eq_desc_clear(&eqdesc[loop]); - qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_qp->tx_vq.fqid); - - if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) - dpaa2_sec_set_enqueue_descriptor( - &dpaa2_qp->tx_vq, - (*ops)->sym->m_src, - &eqdesc[loop]); - else - qbman_eq_desc_set_no_orp(&eqdesc[loop], - DPAA2_EQ_RESP_ERR_FQ); - - /*Clear the unused FD fields before sending*/ - memset(&fd_arr[loop], 0, sizeof(struct qbman_fd)); - mb_pool = (*ops)->sym->m_src->pool; - if (mb_pool->ops_index == - rte_dpaa2_mpool_get_ops_idx()) - bpid = mempool_to_bpid(mb_pool); - else - bpid = MAX_BPID; - ret = build_sec_fd(*ops, &fd_arr[loop], bpid, dpaa2_qp); - if (ret) { - DPAA2_SEC_DP_DEBUG("FD build failed"); - goto skip_tx; - } - ops++; - } - - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - ret = qbman_swp_enqueue_multiple_desc(swp, - &eqdesc[loop], &fd_arr[loop], - frames_to_send - loop); - if (unlikely(ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_ops -= loop; - DPAA2_SEC_DP_DEBUG("Enqueue fail"); - /* freeing the fle buffers */ - while (loop < frames_to_send) { - free_fle(&fd_arr[loop], - dpaa2_qp); - loop++; - } - goto skip_tx; - } - } else { - loop += ret; - retry_count = 0; - } - } - - num_tx += loop; - nb_ops -= loop; - } - -skip_tx: - dpaa2_qp->tx_vq.tx_pkts += num_tx; - dpaa2_qp->tx_vq.err_pkts += nb_ops; - return num_tx; -} - static uint16_t dpaa2_sec_dequeue_burst(void *qp, struct rte_crypto_op **ops, uint16_t nb_ops) @@ -3929,10 +3921,6 @@ dpaa2_sec_dev_start(struct rte_cryptodev *dev) PMD_INIT_FUNC_TRACE(); - /* Change the tx burst function if ordered queues are used */ - if (priv->en_ordered) - dev->enqueue_burst = dpaa2_sec_enqueue_burst_ordered; - memset(&attr, 0, sizeof(struct dpseci_attr)); ret = dpseci_enable(dpseci, CMD_PRI_LOW, priv->token); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 59/65] bus/fslmc: track atomic DCA context per dequeue dpio 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (57 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 58/65] crypto/dpaa2_sec: unify enqueue burst path for ordered enqueue Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 60/65] bus/fslmc: move enqueue response descriptors to per-queue Prashant Gupta ` (5 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> For atomic scheduling the DQRR entry consumed at dequeue must be acknowledged (DCA) from the same DPIO portal that dequeued it. The enqueue and dequeue portals are not guaranteed to be same, so applying the DCA index using the enqueuing's DPIO can acknowledge the wrong portal. This corrupts the held-buffer accounting (dqrr_size / dqrr_held) and leaks DQRR entries on the originating portal. Record the originating dequeue DPIO alongside the sequence number when a frame is dequeued, and only set the DCA and update the held-buffer state when the enqueuing DPIO matches the saved one. The atomic dequeue/enqueue logic that was open-coded in the net, crypto and event drivers is consolidated into shared helpers in dpaa2_hw_pvt.h: - dpaa2_dq_atomic_save() save DQRR index and dequeue DPIO - dpaa2_eq_atomic_consume() consume DCA only if DPIO matches - dpaa2_eq_atomic_dpio_update() release held DQRR after enqueue - dpaa2_mbuf_seq_restore() restore seqn on enqueue failure - dpaa2_mbuf_seq_is_flag_set() test seqn flags The net, crypto and event enqueue paths are updated to use these helpers and to restore the saved sequence number on the enqueue retry / failure path so the DQRR entry can be reclaimed. Ordered (ORP) handling is left unchanged. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 55 ++++++++++++++++ drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 73 +++++++++++---------- drivers/event/dpaa2/dpaa2_eventdev.c | 53 ++++++++------- drivers/net/dpaa2/dpaa2_rxtx.c | 44 +++++-------- 4 files changed, 141 insertions(+), 84 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 1731999257..1ee53c53a2 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -510,6 +510,61 @@ dpaa2_mem_va_to_iova_check(void *va, uint64_t size) #define DPAA2_IOVA_TO_VADDR_AND_CHECK(_iova, size) \ rte_fslmc_cold_mem_iova_to_vaddr(_iova, size) +#define dpaa2_eq_atomic_dpio_update(start, len, dpio, dqrr_size, dqrr_held) \ +({ \ + uint16_t i; \ + \ + for (i = start; i < (uint16_t)(start + len); i++) { \ + dpio->dpaa2_held_bufs.dqrr_size -= dqrr_size[i]; \ + dpio->dpaa2_held_bufs.dqrr_held &= ~dqrr_held[i]; \ + } \ +}) + +#define dpaa2_mbuf_seq_restore(mbuf, restore) \ +({ \ + *dpaa2_seqn(mbuf) = restore; \ +}) + +#define dpaa2_mbuf_seq_is_flag_set(mbuf, flag) \ +({ \ + *dpaa2_seqn(mbuf) & flag; \ +}) + +#define dpaa2_eq_atomic_consume(mbuf, size, held, dpio_eq, flag, eqdesc, atomic) \ +({ \ + uint32_t seqn; \ + \ + if (*dpaa2_seq_dpio_dq(mbuf) == dpio_eq) { \ + seqn = *dpaa2_seqn(mbuf); \ + if (eqdesc) { \ + qbman_eq_desc_set_dca(eqdesc, 1, \ + (seqn & QBMAN_EQCR_DCA_IDXMASK), 0); \ + } \ + if (flag) { \ + *flag = seqn; \ + *dpaa2_seqn(mbuf) = DPAA2_INVALID_MBUF_SEQN; \ + } \ + if (eqdesc || flag) { \ + size = 1; \ + held = UINT64_C(1) << (seqn & QBMAN_EQCR_DCA_IDXMASK); \ + } \ + atomic = true; \ + } \ +}) + +static inline void +dpaa2_dq_atomic_save(const struct qbman_result *dq, + struct rte_mbuf *mbuf, struct dpaa2_dpio_dev *dpio_dev) +{ + uint8_t dqrr_index = qbman_get_dqrr_idx(dq); + + *dpaa2_seqn(mbuf) = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; + *dpaa2_seq_dpio_dq(mbuf) = dpio_dev; + dpio_dev->dpaa2_held_bufs.dqrr_size++; + dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; + dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = mbuf; +} + static inline int check_swp_active_dqs(uint16_t dpio_index) { diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 9d2fa57989..8e0db6a385 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1512,7 +1512,7 @@ dpaa2_sec_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, uint16_t orpid, seqnum; uint8_t dq_idx; - if (*dpaa2_seqn(m) & DPAA2_ENQUEUE_FLAG_ORP) { + if (dpaa2_mbuf_seq_is_flag_set(m, DPAA2_ENQUEUE_FLAG_ORP)) { orpid = (*dpaa2_seqn(m) & DPAA2_EQCR_OPRID_MASK) >> DPAA2_EQCR_OPRID_SHIFT; seqnum = (*dpaa2_seqn(m) & DPAA2_EQCR_SEQNUM_MASK) >> @@ -1548,15 +1548,17 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, uint16_t nb_ops) { /* Function to transmit the frames to given device and VQ*/ - int32_t ret; + int32_t ret, atomic = false; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - uint32_t frames_to_send, num_free_eq_desc, retry_count, loop; + uint32_t num_free_eq_desc, retry_count, flags[MAX_TX_RING_SLOTS]; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; struct dpaa2_sec_qp *dpaa2_qp = qp; struct qbman_swp *swp; - uint16_t num_tx = 0, bpid; - uint8_t dqrr_index; + uint16_t num_tx = 0, bpid, frames_to_send, loop; + uint8_t dqrr_size[MAX_TX_RING_SLOTS]; struct dpaa2_sec_dev_private *priv = dpaa2_qp->tx_vq.crypto_data->dev_private; + struct rte_mbuf *mbuf[MAX_TX_RING_SLOTS]; + uint64_t dqrr_held[MAX_TX_RING_SLOTS]; if (unlikely(!nb_ops)) return 0; @@ -1579,7 +1581,8 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, frames_to_send = (nb_ops > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_ops; if (!priv->en_loose_ordered) { - if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) { + if (dpaa2_mbuf_seq_is_flag_set((*ops)->sym->m_src, + DPAA2_ENQUEUE_FLAG_ORP)) { num_free_eq_desc = dpaa2_free_eq_descriptors(); if (num_free_eq_desc < frames_to_send) frames_to_send = num_free_eq_desc; @@ -1590,18 +1593,20 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc[loop]); qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_qp->tx_vq.fqid); + mbuf[loop] = (*ops)->sym->m_src; - if (*dpaa2_seqn((*ops)->sym->m_src) & DPAA2_ENQUEUE_FLAG_ORP) { + flags[loop] = 0; + dqrr_size[loop] = 0; + dqrr_held[loop] = 0; + if (dpaa2_mbuf_seq_is_flag_set(mbuf[loop], DPAA2_ENQUEUE_FLAG_ORP)) { dpaa2_sec_set_enqueue_descriptor(&dpaa2_qp->tx_vq, - (*ops)->sym->m_src, &eqdesc[loop]); + mbuf[loop], &eqdesc[loop]); } else { - if (*dpaa2_seqn((*ops)->sym->m_src) & QBMAN_ENQUEUE_FLAG_DCA) { - dqrr_index = *dpaa2_seqn((*ops)->sym->m_src) & - QBMAN_EQCR_DCA_IDXMASK; - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dqrr_index); - qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); - *dpaa2_seqn((*ops)->sym->m_src) = DPAA2_INVALID_MBUF_SEQN; + if (dpaa2_mbuf_seq_is_flag_set(mbuf[loop], + QBMAN_ENQUEUE_FLAG_DCA)) { + dpaa2_eq_atomic_consume(mbuf[loop], dqrr_size[loop], + dqrr_held[loop], DPAA2_PER_LCORE_DPIO, + &flags[loop], &eqdesc[loop], atomic); } qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); } @@ -1631,18 +1636,25 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, frames_to_send - loop); if (unlikely(ret < 0)) { retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { - num_tx += loop; - nb_ops -= loop; - DPAA2_SEC_DP_DEBUG("Enqueue fail"); - /* freeing the fle buffers */ - while (loop < frames_to_send) { - free_fle(&fd_arr[loop], dpaa2_qp); - loop++; - } - goto skip_tx; + if (retry_count <= DPAA2_MAX_TX_RETRY_COUNT) + continue; + num_tx += loop; + nb_ops -= loop; + DPAA2_SEC_DP_DEBUG("Failed(%d) to eq %d FDs", + ret, frames_to_send - loop); + /* freeing the fle buffers */ + while (loop < frames_to_send) { + free_fle(&fd_arr[loop], dpaa2_qp); + if (flags[loop]) + dpaa2_mbuf_seq_restore(mbuf[loop], flags[loop]); + loop++; } + goto skip_tx; } else { + if (atomic) { + dpaa2_eq_atomic_dpio_update(loop, ret, DPAA2_PER_LCORE_DPIO, + dqrr_size, dqrr_held); + } loop += ret; retry_count = 0; } @@ -1698,8 +1710,8 @@ dpaa2_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops, frames_to_send = (nb_ops > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_ops; for (loop = 0; loop < frames_to_send; loop++) { - if (*dpaa2_seqn((*ops)->sym->m_src) & - (QBMAN_ENQUEUE_FLAG_DCA | DPAA2_ENQUEUE_FLAG_ORP)) { + if (unlikely(dpaa2_mbuf_seq_is_flag_set((*ops)->sym->m_src, + (DPAA2_ENQUEUE_FLAG_ORP | QBMAN_ENQUEUE_FLAG_DCA)))) { order = true; break; } @@ -4108,7 +4120,6 @@ dpaa2_sec_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, const struct qbman_fd *fd, const struct qbman_result *dq, struct dpaa2_queue *rxq, struct rte_event *ev) { - uint8_t dqrr_index; struct dpaa2_sec_qp *qp; struct rte_crypto_op *crypto_op; @@ -4122,11 +4133,7 @@ dpaa2_sec_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, ev->priority = rxq->ev.priority; crypto_op = dpaa2_sec_fd_to_mbuf(fd, qp); - dqrr_index = qbman_get_dqrr_idx(dq); - *dpaa2_seqn(crypto_op->sym->m_src) = QBMAN_ENQUEUE_FLAG_DCA | dqrr_index; - dpio_dev->dpaa2_held_bufs.dqrr_size++; - dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; - dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = crypto_op->sym->m_src; + dpaa2_dq_atomic_save(dq, crypto_op->sym->m_src, dpio_dev); ev->event_ptr = crypto_op; } diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 2efdbb8b59..8ad9fe7d30 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -124,14 +124,14 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], struct dpaa2_port *dpaa2_portal = port; struct dpaa2_dpio_dev *dpio_dev; struct dpaa2_eventq *evq_info; - uint32_t queue_id, retry_count, loop, frames_to_send, i; + uint32_t queue_id, retry_count, flags[MAX_TX_RING_SLOTS]; struct qbman_swp *swp; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; - uint16_t num_tx = 0; + uint16_t num_tx = 0, loop, _loop, frames_to_send; uint64_t dqrr_held[MAX_TX_RING_SLOTS]; - int ret; - uint8_t dqrr_index, dqrr_size[MAX_TX_RING_SLOTS]; + int ret, atomic = false; + uint8_t dqrr_size[MAX_TX_RING_SLOTS]; const struct rte_event *event; struct dpaa2_queue *dpci_txq[MAX_TX_RING_SLOTS]; struct rte_event *ev_tx[MAX_TX_RING_SLOTS]; @@ -181,15 +181,15 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], qbman_eq_desc_set_fq(&eqdesc[loop], dpci_txq[loop]->fqid); qbman_eq_desc_set_no_orp(&eqdesc[loop], 0); qbman_eq_desc_set_response(&eqdesc[loop], 0, 0); + flags[loop] = 0; dqrr_held[loop] = 0; dqrr_size[loop] = 0; if (event->sched_type == RTE_SCHED_TYPE_ATOMIC && - (*dpaa2_seqn(event->mbuf) & QBMAN_ENQUEUE_FLAG_DCA)) { - dqrr_index = *dpaa2_seqn(event->mbuf) & QBMAN_EQCR_DCA_IDXMASK; - qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); - dqrr_size[loop] = 1; - dqrr_held[loop] = UINT64_C(1) << dqrr_index; + dpaa2_mbuf_seq_is_flag_set(event->mbuf, QBMAN_ENQUEUE_FLAG_DCA)) { + dpaa2_eq_atomic_consume(event->mbuf, dqrr_size[loop], + dqrr_held[loop], dpio_dev, &flags[loop], + &eqdesc[loop], atomic); } memset(&fd_arr[loop], 0, sizeof(struct qbman_fd)); @@ -213,17 +213,22 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], frames_to_send - loop); if (unlikely(ret < 0)) { retry_count++; - if (retry_count > DPAA2_EV_TX_RETRY_COUNT) { - num_tx += loop; - nb_events -= loop; - for (i = loop; i < frames_to_send; i++) - rte_mempool_put(dpci_txq[i]->env_pool, ev_tx[i]); - goto quit; + if (retry_count <= DPAA2_EV_TX_RETRY_COUNT) + continue; + _loop = loop; + while (_loop < frames_to_send) { + rte_mempool_put(dpci_txq[_loop]->env_pool, ev_tx[_loop]); + if (flags[_loop]) { + dpaa2_mbuf_seq_restore(ev[num_tx + _loop].mbuf, + flags[_loop]); + } + _loop++; } + break; } else { - for (i = loop; i < (loop + ret); i++) { - dpio_dev->dpaa2_held_bufs.dqrr_size -= dqrr_size[i]; - dpio_dev->dpaa2_held_bufs.dqrr_held &= ~dqrr_held[i]; + if (unlikely(atomic)) { + dpaa2_eq_atomic_dpio_update(loop, ret, dpio_dev, + dqrr_size, dqrr_held); } loop += ret; retry_count = 0; @@ -231,6 +236,8 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], } num_tx += loop; nb_events -= loop; + if (unlikely(ret < 0)) + break; } quit: @@ -269,14 +276,10 @@ static void dpaa2_eventdev_process_atomic(struct dpaa2_dpio_dev *dpio_dev, struct dpaa2_queue *rxq, struct rte_event *ev) { struct rte_event *rx_ev = (void *)DPAA2_GET_FD_ADDR(fd); - uint8_t dqrr_index = qbman_get_dqrr_idx(dq); rte_memcpy(ev, rx_ev, sizeof(struct rte_event)); rte_mempool_put(rxq->env_pool, rx_ev); - *dpaa2_seqn(ev->mbuf) = dqrr_index | QBMAN_ENQUEUE_FLAG_DCA; - dpio_dev->dpaa2_held_bufs.dqrr_size++; - dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; - dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = ev->mbuf; + dpaa2_dq_atomic_save(dq, ev->mbuf, dpio_dev); } static uint16_t @@ -312,10 +315,10 @@ dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], break; } if (dpio_dev->dpaa2_held_bufs.dqrr_held & (UINT64_C(1) << i)) { + dpaa2_mbuf_seq_restore(dpio_dev->dpaa2_held_bufs.mbuf[i], + DPAA2_INVALID_MBUF_SEQN); qbman_swp_dqrr_idx_consume(swp, i); dpio_dev->dpaa2_held_bufs.dqrr_size--; - *dpaa2_seqn(dpio_dev->dpaa2_held_bufs.mbuf[i]) = - DPAA2_INVALID_MBUF_SEQN; } i++; } diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 56da29a927..149fabc0e2 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1222,8 +1222,6 @@ dpaa2_dev_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, const struct qbman_fd *fd, const struct qbman_result *dq, struct dpaa2_queue *rxq, struct rte_event *ev) { - uint8_t dqrr_index; - if (dpaa2_svr_family != SVR_LX2160A) dpaa2_dev_rx_annot_prefetch(fd); @@ -1233,11 +1231,7 @@ dpaa2_dev_process_atomic_event(struct dpaa2_dpio_dev *dpio_dev, else ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); - dqrr_index = qbman_get_dqrr_idx(dq); - *dpaa2_seqn(ev->mbuf) = dqrr_index | QBMAN_ENQUEUE_FLAG_DCA; - dpio_dev->dpaa2_held_bufs.dqrr_size++; - dpio_dev->dpaa2_held_bufs.dqrr_held |= UINT64_C(1) << dqrr_index; - dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = ev->mbuf; + dpaa2_dq_atomic_save(dq, ev->mbuf, dpio_dev); } void __rte_hot @@ -1581,8 +1575,8 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { - if (unlikely(*dpaa2_seqn((*bufs)) & - (DPAA2_ENQUEUE_FLAG_ORP | QBMAN_ENQUEUE_FLAG_DCA))) { + if (unlikely(dpaa2_mbuf_seq_is_flag_set((*bufs), + (DPAA2_ENQUEUE_FLAG_ORP | QBMAN_ENQUEUE_FLAG_DCA)))) { order = true; break; } @@ -1701,7 +1695,7 @@ dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, qbman_eq_desc_set_fq(eqdesc, dpaa2_q->fqid); - if (*dpaa2_seqn(m) & DPAA2_ENQUEUE_FLAG_ORP) { + if (dpaa2_mbuf_seq_is_flag_set(m, DPAA2_ENQUEUE_FLAG_ORP)) { orpid = (*dpaa2_seqn(m) & DPAA2_EQCR_OPRID_MASK) >> DPAA2_EQCR_OPRID_SHIFT; seqnum = (*dpaa2_seqn(m) & DPAA2_EQCR_SEQNUM_MASK) >> @@ -1741,7 +1735,7 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, { /* Function to transmit the frames to multiple queues respectively.*/ uint32_t loop, retry_count, i; - int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_n, ptp_set; + int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_n, ptp_set, atomic = false; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; uint32_t frames_to_send, num_free_eq_desc = 0; struct rte_mempool *hw_mp; @@ -1750,7 +1744,7 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, struct dpaa2_dev_priv *priv; struct dpaa2_queue *order_sendq; struct dpaa2_queue *cnf_q; - uint8_t dqrr_size[MAX_TX_RING_SLOTS], dqrr_index; + uint8_t dqrr_size[MAX_TX_RING_SLOTS]; uint64_t dqrr_held[MAX_TX_RING_SLOTS]; uint32_t flags[MAX_TX_RING_SLOTS]; @@ -1771,7 +1765,7 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, for (loop = 0; loop < frames_to_send; loop++) { priv = dpaa2_q[loop]->eth_data->dev_private; if (!priv->en_loose_ordered && - (*dpaa2_seqn(bufs[loop]) & DPAA2_ENQUEUE_FLAG_ORP)) { + dpaa2_mbuf_seq_is_flag_set(bufs[loop], DPAA2_ENQUEUE_FLAG_ORP)) { if (!num_free_eq_desc) { num_free_eq_desc = dpaa2_free_eq_descriptors(); if (!num_free_eq_desc) { @@ -1798,20 +1792,17 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, dqrr_held[loop] = 0; dqrr_size[loop] = 0; - if ((*dpaa2_seqn(bufs[loop]) & DPAA2_ENQUEUE_FLAG_ORP) && + if (dpaa2_mbuf_seq_is_flag_set(bufs[loop], DPAA2_ENQUEUE_FLAG_ORP) && priv->en_ordered) { order_sendq = priv->tx_vq[0]; dpaa2_set_enqueue_descriptor(order_sendq, bufs[loop], &eqdesc[loop]); } else { qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); - if (*dpaa2_seqn(bufs[loop]) & QBMAN_ENQUEUE_FLAG_DCA) { - dqrr_index = *dpaa2_seqn(bufs[loop]) & QBMAN_EQCR_DCA_IDXMASK; - dqrr_held[loop] = ~(UINT64_C(1) << dqrr_index); - dqrr_size[loop] = 1; - flags[loop] = *dpaa2_seqn(bufs[loop]); - *dpaa2_seqn(bufs[loop]) = DPAA2_INVALID_MBUF_SEQN; - qbman_eq_desc_set_dca(&eqdesc[loop], 1, dqrr_index, 0); + if (dpaa2_mbuf_seq_is_flag_set(bufs[loop], QBMAN_ENQUEUE_FLAG_DCA)) { + dpaa2_eq_atomic_consume(bufs[loop], dqrr_size[loop], + dqrr_held[loop], DPAA2_PER_LCORE_DPIO, &flags[loop], + &eqdesc[loop], atomic); } } @@ -1857,18 +1848,19 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, ret = qbman_swp_enqueue_multiple_desc(swp, &eqdesc[loop], &fd_arr[loop], frames_to_send - loop); if (likely(ret > 0)) { - for (i = loop; i < (loop + ret); i++) { - DPAA2_PER_LCORE_DQRR_SIZE -= dqrr_size[i]; - DPAA2_PER_LCORE_DQRR_HELD &= ~dqrr_held[i]; - dpaa2_q[i]->tx_pkts++; + if (atomic) { + dpaa2_eq_atomic_dpio_update(loop, ret, DPAA2_PER_LCORE_DPIO, + dqrr_size, dqrr_held); } + for (i = loop; i < (loop + ret); i++) + dpaa2_q[i]->tx_pkts++; loop += ret; retry_count = 0; } else { retry_count++; if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) { for (i = loop; i < frames_to_send; i++) - *dpaa2_seqn(bufs[i]) = flags[i]; + dpaa2_mbuf_seq_restore(bufs[i], flags[i]); break; } } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 60/65] bus/fslmc: move enqueue response descriptors to per-queue 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (58 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 59/65] bus/fslmc: track atomic DCA context per dequeue dpio Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 61/65] event/dpaa2: add ordered schedule type support Prashant Gupta ` (4 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Previously the enqueue (ORP) response descriptors were managed globally per DPIO device via a shared eqresp ring (eqresp, eqresp_meta, eqresp_pi/ci) together with the global helper dpaa2_free_eq_descriptors(). This coupled ordered-enqueue state to the per-core portal and required separate per-driver callbacks (cb_eqresp_free) to free the response buffers. Rework the ordered-enqueue response handling so that each dpaa2_queue owns its own response pool via the new dpaa2_queue_eq_resp structure. Introduce common helpers in dpaa2_hw_pvt.h: - dpaa2_queue_eqresp_create() / dpaa2_queue_eqresp_free() - dpaa2_enq_rsp_process() - dpaa2_eq_set_order_desc() - dpaa2_dq_order_save() / dpaa2_mbuf_seq_order_set() and a unified dpaa2_eqresp_cb callback type. The net and sec drivers are updated to allocate/free the per-queue pool and use the shared order-descriptor and response-processing helpers, removing the duplicated dpaa2_set_enqueue_descriptor() implementations and the old free-eqresp buffer callbacks. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/bus/fslmc/portal/dpaa2_hw_dpio.c | 49 ------ drivers/bus/fslmc/portal/dpaa2_hw_dpio.h | 5 - drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 165 ++++++++++++++++++-- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 89 +++-------- drivers/net/dpaa2/dpaa2_ethdev.c | 5 +- drivers/net/dpaa2/dpaa2_ethdev.h | 3 +- drivers/net/dpaa2/dpaa2_rxtx.c | 87 ++--------- 7 files changed, 195 insertions(+), 208 deletions(-) diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c index a32406b1b3..3e18082e14 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c @@ -765,18 +765,6 @@ dpaa2_create_dpio_device(int vdev_fd, io_space_count++; dpio_dev->index = io_space_count; - dpio_dev->eqresp = rte_zmalloc(NULL, MAX_EQ_RESP_ENTRIES * - (sizeof(struct qbman_result) + - sizeof(struct eqresp_metadata)), - RTE_CACHE_LINE_SIZE); - if (!dpio_dev->eqresp) { - DPAA2_BUS_ERR("Memory allocation failed for eqresp"); - goto err; - } - dpio_dev->eqresp_meta = (struct eqresp_metadata *)(dpio_dev->eqresp + - MAX_EQ_RESP_ENTRIES); - - TAILQ_INSERT_TAIL(&dpio_dev_list, dpio_dev, next); if (!dpaa2_portal_key) { @@ -803,7 +791,6 @@ dpaa2_create_dpio_device(int vdev_fd, dpio_dev->token); } - rte_free(dpio_dev->eqresp); rte_free(dpio_dev->dpio); } @@ -864,42 +851,6 @@ dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage) return -1; } -RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_free_eq_descriptors) -uint32_t -dpaa2_free_eq_descriptors(void) -{ - struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; - struct qbman_result *eqresp; - struct eqresp_metadata *eqresp_meta; - struct dpaa2_queue *txq; - - while (dpio_dev->eqresp_ci != dpio_dev->eqresp_pi) { - eqresp = &dpio_dev->eqresp[dpio_dev->eqresp_ci]; - eqresp_meta = &dpio_dev->eqresp_meta[dpio_dev->eqresp_ci]; - - if (!qbman_result_eqresp_rspid(eqresp)) - break; - - if (qbman_result_eqresp_rc(eqresp)) { - txq = eqresp_meta->dpaa2_q; - txq->cb_eqresp_free(dpio_dev->eqresp_ci, txq); - } - qbman_result_eqresp_set_rspid(eqresp, 0); - - dpio_dev->eqresp_ci + 1 < MAX_EQ_RESP_ENTRIES ? - dpio_dev->eqresp_ci++ : (dpio_dev->eqresp_ci = 0); - } - - /* Return 1 less entry so that PI and CI are never same in a - * case there all the EQ responses are in use. - */ - if (dpio_dev->eqresp_ci > dpio_dev->eqresp_pi) - return dpio_dev->eqresp_ci - dpio_dev->eqresp_pi - 1; - else - return dpio_dev->eqresp_ci - dpio_dev->eqresp_pi + - MAX_EQ_RESP_ENTRIES - 1; -} - static struct rte_dpaa2_object rte_dpaa2_dpio_obj = { .dev_type = DPAA2_IO, .create = dpaa2_create_dpio_device, diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h index c61f8ee0a2..61ed9e0421 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpio.h @@ -65,11 +65,6 @@ __rte_internal void dpaa2_free_dq_storage(struct queue_storage_info_t *q_storage); -/* free the enqueue response descriptors */ -__rte_internal -uint32_t -dpaa2_free_eq_descriptors(void); - __rte_internal struct dpaa2_dpio_dev * rte_dpaa2_alloc_dpio_device(int isr, uint32_t threshold, diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index 1ee53c53a2..b9839eeb70 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -24,6 +24,7 @@ #ifndef true #define true 1 #endif +#undef DPAA2_ORDER_DEBUG #define lower_32_bits(x) ((uint32_t)(x)) #define upper_32_bits(x) ((uint32_t)(((x) >> 16) >> 16)) @@ -54,7 +55,7 @@ #define DPAA2_ENQUEUE_FLAG_ORP (1ULL << 30) /* ORP ID shift and mask */ #define DPAA2_EQCR_OPRID_SHIFT 16 -#define DPAA2_EQCR_OPRID_MASK 0x3FFF0000 +#define DPAA2_EQCR_OPRID_MASK 0x00003FFF /* Sequence number shift and mask */ #define DPAA2_EQCR_SEQNUM_SHIFT 0 #define DPAA2_EQCR_SEQNUM_MASK 0x0000FFFF @@ -89,6 +90,15 @@ #define SEC_FLC_DHR_OUTBOUND (-114) #define SEC_FLC_DHR_INBOUND 0 +static inline __rte_format_printf(1, 2) void +dpaa2_hw_dump(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + rte_vlog(RTE_LOG_NOTICE, RTE_LOGTYPE_USER1, fmt, ap); + va_end(ap); +} + /** Consider aligning with 8 bytes to multiply point size with 2.*/ #define DPAA2_SEC_SIMPLE_FD_OB_MIN \ ((-SEC_FLC_DHR_OUTBOUND) + sizeof(void *) * 2) @@ -98,11 +108,6 @@ struct dpaa2_queue; -struct eqresp_metadata { - struct dpaa2_queue *dpaa2_q; - struct rte_mempool *mp; -}; - #define DPAA2_PORTAL_DEQUEUE_DEPTH 32 struct dpaa2_portal_dqrr { struct rte_mbuf *mbuf[DPAA2_PORTAL_DEQUEUE_DEPTH]; @@ -116,10 +121,6 @@ struct dpaa2_dpio_dev { uint16_t index; /**< Index of a instance in the list */ RTE_ATOMIC(uint16_t) ref_count; /**< How many thread contexts are sharing this.*/ - uint16_t eqresp_ci; - uint16_t eqresp_pi; - struct qbman_result *eqresp; - struct eqresp_metadata *eqresp_meta; struct fsl_mc_io *dpio; /** handle to DPIO portal object */ uint16_t token; struct qbman_swp *sw_portal; /** SW portal object */ @@ -168,8 +169,18 @@ typedef void (dpaa2_queue_cb_dqrr_t)(struct dpaa2_dpio_dev *dpio_dev, struct dpaa2_queue *rxq, struct rte_event *ev); -typedef void (dpaa2_queue_cb_eqresp_free_t)(uint16_t eqresp_ci, - struct dpaa2_queue *dpaa2_q); +typedef void (dpaa2_eqresp_cb)(const struct qbman_fd *fd, + struct dpaa2_queue *dpaa2_q, struct rte_mbuf **pm); + +#define DPAA2_EQRESP_MAX_NUM (MAX_TX_RING_SLOTS * 4) + +struct dpaa2_queue_eq_resp { + struct qbman_result *eqresp_pool; + uint32_t pool_len; + uint16_t active_h; + uint16_t active_t; + dpaa2_eqresp_cb *cb; +}; struct __rte_cache_aligned dpaa2_queue { struct rte_mempool *mb_pool; /**< mbuf pool to populate RX ring. */ @@ -191,11 +202,11 @@ struct __rte_cache_aligned dpaa2_queue { }; void *cfg; uint8_t options; + struct dpaa2_queue_eq_resp eq_resp; struct rte_event ev; struct rte_mempool *env_pool; uint8_t event_attached; dpaa2_queue_cb_dqrr_t *cb; - dpaa2_queue_cb_eqresp_free_t *cb_eqresp_free; struct dpaa2_bp_info *bp_array; /*to store tx_conf_queue corresponding to tx_queue*/ struct dpaa2_queue *tx_conf_queue; @@ -520,6 +531,13 @@ dpaa2_mem_va_to_iova_check(void *va, uint64_t size) } \ }) +#define dpaa2_mbuf_seq_order_set(mbuf, id, seqnum) \ +({ \ + *dpaa2_seqn(mbuf) = DPAA2_ENQUEUE_FLAG_ORP; \ + *dpaa2_seqn(mbuf) |= id << DPAA2_EQCR_OPRID_SHIFT; \ + *dpaa2_seqn(mbuf) |= seqnum << DPAA2_EQCR_SEQNUM_SHIFT; \ +}) + #define dpaa2_mbuf_seq_restore(mbuf, restore) \ ({ \ *dpaa2_seqn(mbuf) = restore; \ @@ -565,6 +583,127 @@ dpaa2_dq_atomic_save(const struct qbman_result *dq, dpio_dev->dpaa2_held_bufs.mbuf[dqrr_index] = mbuf; } +static inline void +dpaa2_dq_order_save(const struct qbman_result *dq, + struct rte_mbuf *mbuf) +{ + uint32_t odpid = qbman_result_DQ_odpid(dq); + uint32_t seqnum = qbman_result_DQ_seqnum(dq); + +#ifdef DPAA2_ORDER_DEBUG + if (odpid > DPAA2_EQCR_OPRID_MASK) { + dpaa2_hw_dump("Critical! too large odp ID(%d)\n", odpid); + return; + } + if (seqnum > DPAA2_EQCR_SEQNUM_MASK) { + dpaa2_hw_dump("Critical! Order seq number(%d) overflows\n", seqnum); + return; + } +#endif + dpaa2_mbuf_seq_order_set(mbuf, odpid, seqnum); +} + +static inline int +dpaa2_queue_eqresp_create(struct dpaa2_queue *queue, + dpaa2_eqresp_cb *cb) +{ + struct dpaa2_queue_eq_resp *eq_resp = &queue->eq_resp; + + eq_resp->eqresp_pool = rte_zmalloc(NULL, + sizeof(struct qbman_result) * DPAA2_EQRESP_MAX_NUM, + RTE_CACHE_LINE_SIZE); + if (!eq_resp->eqresp_pool) + return -ENOBUFS; + eq_resp->pool_len = DPAA2_EQRESP_MAX_NUM; + eq_resp->active_h = 0; + eq_resp->active_t = 0; + eq_resp->cb = cb; + + return 0; +} + +static inline void +dpaa2_enq_rsp_process(struct dpaa2_queue *txq, uint16_t num) +{ + uint16_t i, idx = 0; + struct dpaa2_queue_eq_resp *eq_resp = &txq->eq_resp; + struct qbman_result *eqresp; + struct rte_mbuf *m, *mbufs[MAX_TX_RING_SLOTS]; + + if (likely(eq_resp->active_h == eq_resp->active_t)) + return; + + num = num > MAX_TX_RING_SLOTS ? MAX_TX_RING_SLOTS : num; + + for (i = 0; i < num; i++) { + eqresp = &eq_resp->eqresp_pool[eq_resp->active_h]; + if (!qbman_result_eqresp_rspid(eqresp)) + break; + if (!qbman_result_eqresp_rc(eqresp)) + goto hw_rsp; + + m = NULL; + eq_resp->cb(qbman_result_eqresp_fd(eqresp), txq, &m); + if (m && (!idx || mbufs[0]->pool == m->pool)) { + mbufs[idx] = m; + idx++; + } else if (m) { + rte_pktmbuf_free(m); + } +hw_rsp: + qbman_result_eqresp_set_rspid(eqresp, 0); + eq_resp->active_h = (eq_resp->active_h + 1) & (eq_resp->pool_len - 1); + if (eq_resp->active_h == eq_resp->active_t) + break; + } + if (idx) + rte_pktmbuf_free_bulk(mbufs, idx); +} + +static inline int +dpaa2_eq_set_order_desc(struct dpaa2_queue *dpaa2_q, struct rte_mbuf *m, + struct qbman_eq_desc *eqdesc, int loose_ordered) +{ + uint16_t orpid, seqnum, next; + int rsp; + struct qbman_result *eqresp; + struct dpaa2_queue_eq_resp *eq_resp = &dpaa2_q->eq_resp; + + qbman_eq_desc_set_fq(eqdesc, dpaa2_q->fqid); + orpid = (*dpaa2_seqn(m) >> DPAA2_EQCR_OPRID_SHIFT) & DPAA2_EQCR_OPRID_MASK; + seqnum = (*dpaa2_seqn(m) >> DPAA2_EQCR_SEQNUM_SHIFT) & DPAA2_EQCR_SEQNUM_MASK; + rsp = loose_ordered ? 0 : 1; + qbman_eq_desc_set_orp(eqdesc, rsp, orpid, seqnum, 0); + if (loose_ordered) { + qbman_eq_desc_set_response(eqdesc, 0, 0); + goto orp_quit; + } + + next = (eq_resp->active_t + 1) & (eq_resp->pool_len - 1); + if (next == eq_resp->active_h) + return -EAGAIN; + eqresp = &eq_resp->eqresp_pool[eq_resp->active_t]; + qbman_eq_desc_set_response(eqdesc, DPAA2_VADDR_TO_IOVA(eqresp), 1); + qbman_eq_desc_set_token(eqdesc, 1); + eq_resp->active_t = next; +orp_quit: + *dpaa2_seqn(m) = DPAA2_INVALID_MBUF_SEQN; + + return 0; +} + +static inline void +dpaa2_queue_eqresp_free(struct dpaa2_queue *queue) +{ + while (queue->eq_resp.active_h != queue->eq_resp.active_t) + dpaa2_enq_rsp_process(queue, 1); + if (queue->eq_resp.eqresp_pool) + rte_free(queue->eq_resp.eqresp_pool); + queue->eq_resp.active_h = 0; + queue->eq_resp.active_t = 0; + queue->eq_resp.pool_len = 0; +} + static inline int check_swp_active_dqs(uint16_t dpio_index) { diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index 8e0db6a385..f51c231b99 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1502,47 +1502,6 @@ build_sec_fd(struct rte_crypto_op *op, return ret; } -static void -dpaa2_sec_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, - struct rte_mbuf *m, struct qbman_eq_desc *eqdesc) -{ - struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; - struct eqresp_metadata *eqresp_meta; - struct dpaa2_sec_dev_private *priv = dpaa2_q->crypto_data->dev_private; - uint16_t orpid, seqnum; - uint8_t dq_idx; - - if (dpaa2_mbuf_seq_is_flag_set(m, DPAA2_ENQUEUE_FLAG_ORP)) { - orpid = (*dpaa2_seqn(m) & DPAA2_EQCR_OPRID_MASK) >> - DPAA2_EQCR_OPRID_SHIFT; - seqnum = (*dpaa2_seqn(m) & DPAA2_EQCR_SEQNUM_MASK) >> - DPAA2_EQCR_SEQNUM_SHIFT; - - if (!priv->en_loose_ordered) { - qbman_eq_desc_set_orp(eqdesc, 1, orpid, seqnum, 0); - qbman_eq_desc_set_response(eqdesc, (uint64_t) - DPAA2_VADDR_TO_IOVA(&dpio_dev->eqresp[ - dpio_dev->eqresp_pi]), 1); - qbman_eq_desc_set_token(eqdesc, 1); - - eqresp_meta = &dpio_dev->eqresp_meta[dpio_dev->eqresp_pi]; - eqresp_meta->dpaa2_q = dpaa2_q; - eqresp_meta->mp = m->pool; - - dpio_dev->eqresp_pi + 1 < MAX_EQ_RESP_ENTRIES ? - dpio_dev->eqresp_pi++ : (dpio_dev->eqresp_pi = 0); - } else { - qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0); - } - } else { - dq_idx = *dpaa2_seqn(m) & QBMAN_EQCR_DCA_IDXMASK; - qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0); - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dq_idx); - } - *dpaa2_seqn(m) = DPAA2_INVALID_MBUF_SEQN; -} - static uint16_t dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, uint16_t nb_ops) @@ -1550,7 +1509,7 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, /* Function to transmit the frames to given device and VQ*/ int32_t ret, atomic = false; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - uint32_t num_free_eq_desc, retry_count, flags[MAX_TX_RING_SLOTS]; + uint32_t retry_count, flags[MAX_TX_RING_SLOTS]; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; struct dpaa2_sec_qp *dpaa2_qp = qp; struct qbman_swp *swp; @@ -1576,31 +1535,24 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, } } swp = DPAA2_PER_LCORE_PORTAL; + dpaa2_enq_rsp_process(&dpaa2_qp->tx_vq, nb_ops); while (nb_ops) { frames_to_send = (nb_ops > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_ops; - if (!priv->en_loose_ordered) { - if (dpaa2_mbuf_seq_is_flag_set((*ops)->sym->m_src, - DPAA2_ENQUEUE_FLAG_ORP)) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (num_free_eq_desc < frames_to_send) - frames_to_send = num_free_eq_desc; - } - } - for (loop = 0; loop < frames_to_send; loop++) { /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc[loop]); - qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_qp->tx_vq.fqid); mbuf[loop] = (*ops)->sym->m_src; flags[loop] = 0; dqrr_size[loop] = 0; dqrr_held[loop] = 0; if (dpaa2_mbuf_seq_is_flag_set(mbuf[loop], DPAA2_ENQUEUE_FLAG_ORP)) { - dpaa2_sec_set_enqueue_descriptor(&dpaa2_qp->tx_vq, - mbuf[loop], &eqdesc[loop]); + ret = dpaa2_eq_set_order_desc(&dpaa2_qp->tx_vq, mbuf[loop], + &eqdesc[loop], priv->en_loose_ordered); + if (ret) + goto skip_tx; } else { if (dpaa2_mbuf_seq_is_flag_set(mbuf[loop], QBMAN_ENQUEUE_FLAG_DCA)) { @@ -1608,6 +1560,7 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, dqrr_held[loop], DPAA2_PER_LCORE_DPIO, &flags[loop], &eqdesc[loop], atomic); } + qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_qp->tx_vq.fqid); qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); } @@ -1954,21 +1907,21 @@ dpaa2_sec_dump(struct rte_crypto_op *op, FILE *f) } static void -dpaa2_sec_free_eqresp_buf(uint16_t eqresp_ci, - struct dpaa2_queue *dpaa2_q) +dpaa2_sec_eqresp_cb(const struct qbman_fd *fd, struct dpaa2_queue *dpaa2_q, + struct rte_mbuf **pm) { - struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; struct rte_crypto_op *op; - struct qbman_fd *fd; struct dpaa2_sec_qp *dpaa2_qp; dpaa2_qp = container_of(dpaa2_q, struct dpaa2_sec_qp, tx_vq); - fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); op = dpaa2_sec_fd_to_mbuf(fd, dpaa2_qp); /* Instead of freeing, enqueue it to the sec tx queue (sec->core) * after setting an error in FD. But this will have performance impact. */ - rte_pktmbuf_free(op->sym->m_src); + if (pm) + *pm = op->sym->m_src; + else + rte_pktmbuf_free(op->sym->m_src); } static uint16_t @@ -2083,6 +2036,7 @@ dpaa2_sec_queue_pair_release(struct rte_cryptodev *dev, uint16_t queue_pair_id) dpaa2_queue_storage_free(&qp->rx_vq, 1); rte_mempool_free(qp->fle_pool); + dpaa2_queue_eqresp_free(&qp->tx_vq); rte_free(qp); dev->data->queue_pairs[queue_pair_id] = NULL; @@ -2153,6 +2107,14 @@ dpaa2_sec_queue_pair_setup(struct rte_cryptodev *dev, uint16_t qp_id, return -ENOMEM; } + retcode = dpaa2_queue_eqresp_create(&qp->tx_vq, dpaa2_sec_eqresp_cb); + if (retcode) { + rte_mempool_free(qp->fle_pool); + qp->fle_pool = NULL; + dpaa2_queue_storage_free((&qp->rx_vq), 1); + return retcode; + } + cfg.dest_cfg.dest_type = DPSECI_DEST_NONE; retcode = dpseci_set_rx_queue(dpseci, CMD_PRI_LOW, priv->token, qp_id, &cfg); @@ -4156,11 +4118,7 @@ dpaa2_sec_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, ev->priority = rxq->ev.priority; crypto_op = dpaa2_sec_fd_to_mbuf(fd, qp); - *dpaa2_seqn(crypto_op->sym->m_src) = DPAA2_ENQUEUE_FLAG_ORP; - *dpaa2_seqn(crypto_op->sym->m_src) |= qbman_result_DQ_odpid(dq) << - DPAA2_EQCR_OPRID_SHIFT; - *dpaa2_seqn(crypto_op->sym->m_src) |= qbman_result_DQ_seqnum(dq) << - DPAA2_EQCR_SEQNUM_SHIFT; + dpaa2_dq_order_save(dq, crypto_op->sym->m_src); qbman_swp_dqrr_consume(swp, dq); ev->event_ptr = crypto_op; @@ -4231,7 +4189,6 @@ dpaa2_sec_eventq_attach(const struct rte_cryptodev *dev, DPAA2_SEC_ERR("Error setting opr: ret: %d", ret); return ret; } - qp->tx_vq.cb_eqresp_free = dpaa2_sec_free_eqresp_buf; priv->en_ordered = 1; } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 85c93bf422..b75625dc01 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1192,6 +1192,7 @@ dpaa2_free_rx_tx_queues(struct rte_eth_dev *dev) /* cleanup tx queue cscn */ for (i = 0; i < priv->nb_tx_queues; i++) { dpaa2_q = priv->tx_vq[i]; + dpaa2_queue_eqresp_free(dpaa2_q); rte_free(dpaa2_q->cscn); priv->tx_vq[i] = NULL; } @@ -1858,7 +1859,9 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, return ret; } } - dpaa2_q->cb_eqresp_free = dpaa2_dev_free_eqresp_buf; + ret = dpaa2_queue_eqresp_create(dpaa2_q, dpaa2_dev_eqresp_cb); + if (ret) + return ret; dev->data->tx_queues[tx_queue_id] = dpaa2_q; if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index caf3fabee7..491ad78d85 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -977,7 +977,8 @@ __rte_internal uint16_t dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, struct rte_mbuf **bufs, uint16_t nb_pkts); -void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); +void dpaa2_dev_eqresp_cb(const struct qbman_fd *fd, + struct dpaa2_queue *dpaa2_q, struct rte_mbuf **pm); void dpaa2_flow_clean(struct rte_eth_dev *dev, uint8_t tc_id, enum dpaa2_flow_dist_type type); uint16_t dpaa2_dev_tx_conf(struct dpaa2_queue *tx_conf_q, int drain); diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 149fabc0e2..fec046deaf 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1250,9 +1250,7 @@ dpaa2_dev_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, else ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); - *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; - *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; - *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_seqnum(dq) << DPAA2_EQCR_SEQNUM_SHIFT; + dpaa2_dq_order_save(dq, ev->mbuf); qbman_swp_dqrr_consume(swp, dq); } @@ -1665,84 +1663,35 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } void -dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, - __rte_unused struct dpaa2_queue *dpaa2_q) +dpaa2_dev_eqresp_cb(const struct qbman_fd *fd, + struct dpaa2_queue *dpaa2_q, struct rte_mbuf **pm) { - struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; - struct qbman_fd *fd; struct rte_mbuf *m; - fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); - /* Setting port id does not matter as we are to free the mbuf */ if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); else m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); - if (m) + if (pm) + *pm = m; + else if (m) rte_pktmbuf_free(m); } -static void -dpaa2_set_enqueue_descriptor(struct dpaa2_queue *dpaa2_q, - struct rte_mbuf *m, struct qbman_eq_desc *eqdesc) -{ - struct dpaa2_dev_priv *priv = dpaa2_q->eth_data->dev_private; - struct dpaa2_dpio_dev *dpio_dev = DPAA2_PER_LCORE_DPIO; - struct eqresp_metadata *eqresp_meta; - uint16_t orpid, seqnum; - uint8_t dq_idx; - - qbman_eq_desc_set_fq(eqdesc, dpaa2_q->fqid); - - if (dpaa2_mbuf_seq_is_flag_set(m, DPAA2_ENQUEUE_FLAG_ORP)) { - orpid = (*dpaa2_seqn(m) & DPAA2_EQCR_OPRID_MASK) >> - DPAA2_EQCR_OPRID_SHIFT; - seqnum = (*dpaa2_seqn(m) & DPAA2_EQCR_SEQNUM_MASK) >> - DPAA2_EQCR_SEQNUM_SHIFT; - - if (!priv->en_loose_ordered) { - qbman_eq_desc_set_orp(eqdesc, 1, orpid, seqnum, 0); - qbman_eq_desc_set_response(eqdesc, (uint64_t) - DPAA2_VADDR_TO_IOVA(&dpio_dev->eqresp[ - dpio_dev->eqresp_pi]), 1); - qbman_eq_desc_set_token(eqdesc, 1); - - eqresp_meta = &dpio_dev->eqresp_meta[ - dpio_dev->eqresp_pi]; - eqresp_meta->dpaa2_q = dpaa2_q; - eqresp_meta->mp = m->pool; - - dpio_dev->eqresp_pi + 1 < MAX_EQ_RESP_ENTRIES ? - dpio_dev->eqresp_pi++ : - (dpio_dev->eqresp_pi = 0); - } else { - qbman_eq_desc_set_orp(eqdesc, 0, orpid, seqnum, 0); - } - } else { - dq_idx = *dpaa2_seqn(m) & QBMAN_EQCR_DCA_IDXMASK; - qbman_eq_desc_set_dca(eqdesc, 1, dq_idx, 0); - DPAA2_PER_LCORE_DQRR_SIZE--; - DPAA2_PER_LCORE_DQRR_HELD &= ~(UINT64_C(1) << dq_idx); - } - *dpaa2_seqn(m) = DPAA2_INVALID_MBUF_SEQN; -} - RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_dev_tx_multi_txq_ordered) uint16_t dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to multiple queues respectively.*/ - uint32_t loop, retry_count, i; + uint32_t loop, retry_count, i, frames_to_send; int32_t ret = 0, tstamp[MAX_TX_RING_SLOTS], ptp_n, ptp_set, atomic = false; struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; - uint32_t frames_to_send, num_free_eq_desc = 0; struct rte_mempool *hw_mp; struct qbman_eq_desc eqdesc[MAX_TX_RING_SLOTS]; struct qbman_swp *swp; struct dpaa2_dev_priv *priv; - struct dpaa2_queue *order_sendq; struct dpaa2_queue *cnf_q; uint8_t dqrr_size[MAX_TX_RING_SLOTS]; uint64_t dqrr_held[MAX_TX_RING_SLOTS]; @@ -1757,24 +1706,14 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, } } swp = DPAA2_PER_LCORE_PORTAL; + for (loop = 0; loop < nb_pkts; loop++) + dpaa2_enq_rsp_process(dpaa2_q[loop], 1); ptp_n = 0; - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? - dpaa2_eqcr_size : nb_pkts; + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; for (loop = 0; loop < frames_to_send; loop++) { priv = dpaa2_q[loop]->eth_data->dev_private; - if (!priv->en_loose_ordered && - dpaa2_mbuf_seq_is_flag_set(bufs[loop], DPAA2_ENQUEUE_FLAG_ORP)) { - if (!num_free_eq_desc) { - num_free_eq_desc = dpaa2_free_eq_descriptors(); - if (!num_free_eq_desc) { - ret = -EIO; - goto send_frames; - } - } - num_free_eq_desc--; - } /* Check if the queue is congested */ retry_count = 0; @@ -1794,8 +1733,10 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, dqrr_size[loop] = 0; if (dpaa2_mbuf_seq_is_flag_set(bufs[loop], DPAA2_ENQUEUE_FLAG_ORP) && priv->en_ordered) { - order_sendq = priv->tx_vq[0]; - dpaa2_set_enqueue_descriptor(order_sendq, bufs[loop], &eqdesc[loop]); + ret = dpaa2_eq_set_order_desc(priv->tx_vq[0], bufs[loop], &eqdesc[loop], + priv->en_loose_ordered); + if (ret) + goto send_frames; } else { qbman_eq_desc_set_no_orp(&eqdesc[loop], DPAA2_EQ_RESP_ERR_FQ); qbman_eq_desc_set_fq(&eqdesc[loop], dpaa2_q[loop]->fqid); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 61/65] event/dpaa2: add ordered schedule type support 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (59 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 60/65] bus/fslmc: move enqueue response descriptors to per-queue Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 62/65] bus/fslmc: make DPAA2 ORP/ODP ordering per-queue instead of per-device Prashant Gupta ` (3 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The dpaa2 eventdev supported only PARALLEL and ATOMIC schedule types. Each schedule type uses its own DPCI Tx queue (dpci_txqs[] indexed by event->sched_type) attached with a dedicated dequeue callback, and the ORDERED slot was left unimplemented (marked TODO). Add RTE_SCHED_TYPE_ORDERED support: - Attach the ordered DPCI queue (dpci_txqs[RTE_SCHED_TYPE_ORDERED]) with a new dequeue callback dpaa2_eventdev_process_order() that saves the ORP context via dpaa2_dq_order_save(). - Advertise RTE_EVENT_DEV_CAP_NONSEQ_MODE and accept RTE_SCHED_TYPE_ORDERED in queue setup. - Handle the ORP flag in the enqueue path via dpaa2_eq_set_order_desc(). Also optimize the Tx adapter enqueue path to use rte_eth_tx_burst() directly when all packets target the same queue and no ordered/atomic (ORP or DCA) handling is required, falling back to dpaa2_dev_tx_multi_txq_ordered() otherwise. The DPCI attach error logs are reworded from "RX" to "qp" for clarity. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 84 +++++++++++++++++++++------- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 8ad9fe7d30..a03b04a057 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -178,18 +178,29 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], /* Prepare enqueue descriptor */ qbman_eq_desc_clear(&eqdesc[loop]); - qbman_eq_desc_set_fq(&eqdesc[loop], dpci_txq[loop]->fqid); - qbman_eq_desc_set_no_orp(&eqdesc[loop], 0); - qbman_eq_desc_set_response(&eqdesc[loop], 0, 0); flags[loop] = 0; dqrr_held[loop] = 0; dqrr_size[loop] = 0; - if (event->sched_type == RTE_SCHED_TYPE_ATOMIC && - dpaa2_mbuf_seq_is_flag_set(event->mbuf, QBMAN_ENQUEUE_FLAG_DCA)) { - dpaa2_eq_atomic_consume(event->mbuf, dqrr_size[loop], - dqrr_held[loop], dpio_dev, &flags[loop], - &eqdesc[loop], atomic); + if (event->sched_type == RTE_SCHED_TYPE_ORDERED && + dpaa2_mbuf_seq_is_flag_set(event->mbuf, DPAA2_ENQUEUE_FLAG_ORP)) { + ret = dpaa2_eq_set_order_desc(dpci_txq[loop], event->mbuf, + &eqdesc[loop], true); + if (ret) { + rte_mempool_put(dpci_txq[loop]->env_pool, ev_tx[loop]); + goto send_partial; + } + } else { + if (event->sched_type == RTE_SCHED_TYPE_ATOMIC && + dpaa2_mbuf_seq_is_flag_set(event->mbuf, + QBMAN_ENQUEUE_FLAG_DCA)) { + dpaa2_eq_atomic_consume(event->mbuf, dqrr_size[loop], + dqrr_held[loop], dpio_dev, &flags[loop], + &eqdesc[loop], atomic); + } + qbman_eq_desc_set_fq(&eqdesc[loop], dpci_txq[loop]->fqid); + qbman_eq_desc_set_no_orp(&eqdesc[loop], 0); + qbman_eq_desc_set_response(&eqdesc[loop], 0, 0); } memset(&fd_arr[loop], 0, sizeof(struct qbman_fd)); @@ -258,16 +269,23 @@ static void dpaa2_eventdev_dequeue_wait(struct dpaa2_dpio_dev *dpio_dev, DPAA2_PMD_DP_DEBUG("%s: poll return(%d)", __func__, ret); } -static void dpaa2_eventdev_process_parallel(struct dpaa2_dpio_dev *dpio_dev, - const struct qbman_fd *fd, const struct qbman_result *dq, +static inline void +dpaa2_eventdev_rx_get_event(const struct qbman_fd *fd, struct dpaa2_queue *rxq, struct rte_event *ev) { struct rte_event *rx_ev = (void *)DPAA2_GET_FD_ADDR(fd); - struct qbman_swp *swp = dpio_dev->sw_portal; rte_memcpy(ev, rx_ev, sizeof(struct rte_event)); rte_mempool_put(rxq->env_pool, rx_ev); +} +static void dpaa2_eventdev_process_parallel(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) +{ + struct qbman_swp *swp = dpio_dev->sw_portal; + + dpaa2_eventdev_rx_get_event(fd, rxq, ev); qbman_swp_dqrr_consume(swp, dq); } @@ -275,13 +293,21 @@ static void dpaa2_eventdev_process_atomic(struct dpaa2_dpio_dev *dpio_dev, const struct qbman_fd *fd, const struct qbman_result *dq, struct dpaa2_queue *rxq, struct rte_event *ev) { - struct rte_event *rx_ev = (void *)DPAA2_GET_FD_ADDR(fd); - - rte_memcpy(ev, rx_ev, sizeof(struct rte_event)); - rte_mempool_put(rxq->env_pool, rx_ev); + dpaa2_eventdev_rx_get_event(fd, rxq, ev); dpaa2_dq_atomic_save(dq, ev->mbuf, dpio_dev); } +static void dpaa2_eventdev_process_order(struct dpaa2_dpio_dev *dpio_dev, + const struct qbman_fd *fd, const struct qbman_result *dq, + struct dpaa2_queue *rxq, struct rte_event *ev) +{ + struct qbman_swp *swp = dpio_dev->sw_portal; + + dpaa2_eventdev_rx_get_event(fd, rxq, ev); + dpaa2_dq_order_save(dq, ev->mbuf); + qbman_swp_dqrr_consume(swp, dq); +} + static uint16_t dpaa2_eventdev_dequeue_burst(void *port, struct rte_event ev[], uint16_t nb_events, uint64_t timeout_ticks) @@ -439,6 +465,7 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev, RTE_EVENT_DEV_CAP_RUNTIME_PORT_LINK | RTE_EVENT_DEV_CAP_MULTIPLE_QUEUE_PORT | RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES | + RTE_EVENT_DEV_CAP_NONSEQ_MODE | RTE_EVENT_DEV_CAP_CARRY_FLOW_ID | RTE_EVENT_DEV_CAP_MAINTENANCE_FREE; dev_info->max_profiles_per_port = 1; @@ -653,6 +680,7 @@ dpaa2_eventdev_queue_setup(struct rte_eventdev *dev, uint8_t queue_id, switch (queue_conf->schedule_type) { case RTE_SCHED_TYPE_PARALLEL: case RTE_SCHED_TYPE_ATOMIC: + case RTE_SCHED_TYPE_ORDERED: break; default: DPAA2_EVENTDEV_ERR("Schedule type(%d) is not supported.", @@ -1169,6 +1197,7 @@ dpaa2_eventdev_txa_enqueue(void *port, struct dpaa2_queue *txq[MAX_TX_RING_SLOTS]; struct rte_mbuf *m[MAX_TX_RING_SLOTS]; uint16_t sent = 0, burst, i, port_id, qid; + int same_q, order; RTE_SET_USED(port); @@ -1176,15 +1205,25 @@ dpaa2_eventdev_txa_enqueue(void *port, * on-stack burst array, so transmit in ring-sized chunks. */ while (sent < nb_events) { + same_q = true; + order = false; burst = RTE_MIN(nb_events - sent, (uint16_t)RTE_DIM(m)); for (i = 0; i < burst; i++) { m[i] = ev[sent + i].mbuf; port_id = m[i]->port; qid = rte_event_eth_tx_adapter_txq_get(m[i]); txq[i] = rte_eth_devices[port_id].data->tx_queues[qid]; + if (same_q && i > 0 && txq[i] != txq[i - 1]) + same_q = false; + if (!order && dpaa2_mbuf_seq_is_flag_set(m[i], + (DPAA2_ENQUEUE_FLAG_ORP | QBMAN_ENQUEUE_FLAG_DCA))) + order = true; } - i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); + if (same_q && !order && burst > 0) + i = rte_eth_tx_burst(port_id, qid, m, burst); + else + i = dpaa2_dev_tx_multi_txq_ordered(txq, m, burst); sent += i; if (i < burst) break; @@ -1283,7 +1322,7 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) dpaa2_eventdev_process_parallel, &evq_info->dpci_txqs[RTE_SCHED_TYPE_PARALLEL]); if (ret) { - DPAA2_EVENTDEV_ERR("DPCI attach parallel RX failed: err(%d)", ret); + DPAA2_EVENTDEV_ERR("DPCI attach parallel qp failed: err(%d)", ret); goto err_break; } @@ -1292,11 +1331,18 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) dpaa2_eventdev_process_atomic, &evq_info->dpci_txqs[RTE_SCHED_TYPE_ATOMIC]); if (ret) { - DPAA2_EVENTDEV_ERR("DPCI attach atomic RX failed: err(%d)", ret); + DPAA2_EVENTDEV_ERR("DPCI attach atomic qp failed: err(%d)", ret); goto err_break; } - /** TO DO: order schedule.*/ + ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, + dpcon_dev->dpcon_id, 0, + dpaa2_eventdev_process_order, + &evq_info->dpci_txqs[RTE_SCHED_TYPE_ORDERED]); + if (ret) { + DPAA2_EVENTDEV_ERR("DPCI attach order qp failed: err(%d)", ret); + goto err_break; + } evq_info->valid = true; evq_info->event_queue_id = priv->max_event_queues; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 62/65] bus/fslmc: make DPAA2 ORP/ODP ordering per-queue instead of per-device 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (60 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 61/65] event/dpaa2: add ordered schedule type support Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 63/65] event/dpaa2: support multi-port enqueue in selftest random event generator Prashant Gupta ` (2 subsequent siblings) 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 ORP (Order Restoration Point) / ODP ordering state used to be tracked with device-wide flags (en_ordered / en_loose_ordered in both dpaa2_sec_dev_private and dpaa2_dev_priv). That is fundamentally wrong: ORP/ODP is a per-queue property on DPAA2 hardware -- different RX queues on the same DPNI / DPSECI / DPCI can independently be configured as unordered, atomic (hold-active), loose-ORP or strict-ORP. Collapsing it to a single per-device flag meant the first queue's ordering mode silently dictated the behavior of all others, and prevented mixing ordering modes on one device. This patch moves the ordering mode onto struct dpaa2_queue itself and refactors all DPAA2 drivers to consult that per-queue field on both the RX (dequeue/order-save) and TX (enqueue/order-restore) paths. Main changes: - drivers/bus/fslmc (common): * New enum dpaa2_queue_order_type { NONE, HOLD_ACTIVE, LOOSE_ORP, STRICT_ORP } and a matching order_type field in struct dpaa2_queue -- this is now the single source of truth, per queue. * New dpaa2_orp_config_helper() centralizing struct opr_cfg setup (oprrws per SoC, oa, olws, oeane, oloe) for strict vs loose ORP, replacing three near-identical copies that lived in the sec/eth drivers. * Encode the strict/loose bit into the mbuf seqn (new DPAA2_EQCR_STRICT_SHIFT/MASK; OPRID mask narrowed to 0x1FFF to make room). dpaa2_mbuf_seq_order_set() and dpaa2_dq_order_save() now carry the per-queue ordering type end-to-end, so TX no longer has to look up any device-level flag. * dpaa2_eq_set_order_desc() derives the ORP response/strict flag from the mbuf seqn instead of a per-call loose_ordered argument. * rte_dpaa2_dpci_link_attach() gains an order_type parameter and programs DPCI_QUEUE_OPT_HOLD_ACTIVE / order_preservation_en / dpci_set_opr() per queue, recording the result on that RX queue. - drivers/crypto/dpaa2_sec: * Remove device-wide en_ordered from dpaa2_sec_dev_private. * dpaa2_sec_eventq_attach() uses dpaa2_orp_config_helper() and stores the chosen order_type on the SEC qp's rx_vq. * Ordered enqueue and dpaa2_sec_process_ordered_event() consult the per-queue order_type rather than the removed device flags. - drivers/event/dpaa2: * Pass the appropriate per-queue order_type (NONE / HOLD_ACTIVE / LOOSE_ORP) when attaching parallel/atomic/ordered DPCI queues. * Enqueue and process-order paths use the new per-queue API. - drivers/net/dpaa2: * Remove en_ordered / en_loose_ordered from dpaa2_dev_priv. * dpaa2_eth_eventq_attach() uses dpaa2_orp_config_helper(), honoring DPAA2_STRICT_ORDERING_ENABLE, and records the resulting order_type on the specific RXQ being attached. * tx_multi_txq_ordered() and process_ordered_event() use the per-queue order_type instead of device-level flags. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- doc/guides/nics/dpaa2.rst | 4 + drivers/bus/fslmc/portal/dpaa2_hw_dpci.c | 81 +++++++++++++++++---- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 56 ++++++++++++-- drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 41 ++++------- drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h | 1 - drivers/event/dpaa2/dpaa2_eventdev.c | 10 +-- drivers/event/dpaa2/dpaa2_scheduler.c | 2 +- drivers/net/dpaa2/dpaa2_ethdev.c | 44 ++++------- drivers/net/dpaa2/dpaa2_ethdev.h | 4 +- drivers/net/dpaa2/dpaa2_rxtx.c | 8 +- 10 files changed, 158 insertions(+), 93 deletions(-) diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index 6c67a76f12..4d927cefc2 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -503,6 +503,10 @@ Refer to the document :doc:`build_and_test` for details. create, destroy and update operations. e.g. ``fslmc:dpni.1,drv_flow_api_debug=1`` +* Use dev arg option ``drv_queue_strict_order=1`` to enable strict ordering on + the ordered event queue. + e.g. ``fslmc:dpni.1,drv_queue_strict_order=1`` + * Use dev arg option ``drv_error_queue=1`` to enable Packets in Error queue. DPAA2 hardware drops the error packet in hardware. This option enables the hardware to not drop the error packet and let the driver dump the error diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c b/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c index f796875010..680249cf95 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c +++ b/drivers/bus/fslmc/portal/dpaa2_hw_dpci.c @@ -259,15 +259,50 @@ dpaa2_close_dpci_device(int object_id) } } +static int +dpaa2_dpci_set_opr(struct dpaa2_dpci_dev *dpci_dev, uint8_t rxq_idx, int strict) +{ + int ret, orp_ret; + struct opr_cfg ocfg; + + dpaa2_orp_config_helper(&ocfg, strict); + + ret = dpci_disable(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to disable DPCI.%d before setting opr", + ret, dpci_dev->dpci_id); + return ret; + } + + orp_ret = dpci_set_opr(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token, + rxq_idx, OPR_OPT_CREATE, &ocfg); + if (orp_ret) { + DPAA2_BUS_ERR("Failed(%d) to set opr of DPCI.%d's rxq.%d", + orp_ret, dpci_dev->dpci_id, rxq_idx); + /** Enable anyway.*/ + } + + ret = dpci_enable(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token); + if (ret) { + DPAA2_BUS_ERR("Failed(%d) to enable DPCI.%d after setting opr", + ret, dpci_dev->dpci_id); + return ret; + } + + return orp_ret; +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_dpci_link_attach) int rte_dpaa2_dpci_link_attach(struct dpaa2_dpci_dev *dpci_dev, enum dpci_dest dest_type, uint32_t dest_id, uint8_t priority, - dpaa2_queue_cb_dqrr_t *rx_cb, struct dpaa2_queue **txq) + dpaa2_queue_cb_dqrr_t *rx_cb, enum dpaa2_queue_order_type order_type, + struct dpaa2_queue **txq) { + struct dpaa2_queue *rx_queue = NULL; struct dpci_rx_queue_cfg rx_queue_cfg; uint16_t i; - int ret; + int ret, strict = false; struct dpaa2_dpci_dev *peer_dpci; memset(&rx_queue_cfg, 0, sizeof(struct dpci_rx_queue_cfg)); @@ -282,24 +317,43 @@ rte_dpaa2_dpci_link_attach(struct dpaa2_dpci_dev *dpci_dev, } } - /*Do settings to get the frame on a DPCON object*/ - rx_queue_cfg.options = DPCI_QUEUE_OPT_DEST | - DPCI_QUEUE_OPT_USER_CTX; - rx_queue_cfg.dest_cfg.dest_type = dest_type; - rx_queue_cfg.dest_cfg.dest_id = dest_id; - rx_queue_cfg.dest_cfg.priority = priority; - rx_queue_cfg.order_preservation_en = 0; - for (i = 0; i < dpci_dev->rx_queue_num; i++) { - if (!dpci_dev->rx_queue[i].cb) + if (!dpci_dev->rx_queue[i].event_attached) break; } if (i >= dpci_dev->rx_queue_num || i >= dpci_dev->tx_queue_num) { DPAA2_BUS_ERR("DPCI.%d No queue pair available!", dpci_dev->dpci_id); return -EBUSY; } + rx_queue = &dpci_dev->rx_queue[i]; + + rx_queue->order_type = DPAA2_QUEUE_NONE_ORDER; + /*Do settings to get the frame on a DPCON object*/ + rx_queue_cfg.options = DPCI_QUEUE_OPT_DEST | DPCI_QUEUE_OPT_USER_CTX; + if (order_type == DPAA2_QUEUE_HOLD_ACTIVE_ORDER) { + rx_queue_cfg.options |= DPCI_QUEUE_OPT_HOLD_ACTIVE; + rx_queue_cfg.order_preservation_en = true; + rx_queue->order_type = DPAA2_QUEUE_HOLD_ACTIVE_ORDER; + } else { + rx_queue_cfg.order_preservation_en = false; + if (order_type == DPAA2_QUEUE_LOOSE_ORP_ORDER || + order_type == DPAA2_QUEUE_STRICT_ORP_ORDER) { + if (order_type == DPAA2_QUEUE_STRICT_ORP_ORDER) + strict = true; + ret = dpaa2_dpci_set_opr(dpci_dev, i, strict); + if (ret) + return ret; + if (strict) + rx_queue->order_type = DPAA2_QUEUE_STRICT_ORP_ORDER; + else + rx_queue->order_type = DPAA2_QUEUE_LOOSE_ORP_ORDER; + } + } + rx_queue_cfg.dest_cfg.dest_type = dest_type; + rx_queue_cfg.dest_cfg.dest_id = dest_id; + rx_queue_cfg.dest_cfg.priority = priority; - rx_queue_cfg.user_ctx = (uint64_t)(&dpci_dev->rx_queue[i]); + rx_queue_cfg.user_ctx = (uint64_t)rx_queue; ret = dpci_set_rx_queue(&dpci_dev->dpci, CMD_PRI_LOW, dpci_dev->token, i, &rx_queue_cfg); if (ret) { @@ -307,8 +361,9 @@ rte_dpaa2_dpci_link_attach(struct dpaa2_dpci_dev *dpci_dev, dpci_dev->dpci_id, i, ret); return ret; } - dpci_dev->rx_queue[i].cb = rx_cb; + rx_queue->cb = rx_cb; dpci_dev->tx_queue[i].env_pool = peer_dpci->rx_queue[i].env_pool; + rx_queue->event_attached++; if (txq) *txq = &dpci_dev->tx_queue[i]; diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h index b9839eeb70..d7dc88ca35 100644 --- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h @@ -53,9 +53,11 @@ /* Flag to determine an ordered queue mbuf */ #define DPAA2_ENQUEUE_FLAG_ORP (1ULL << 30) +#define DPAA2_EQCR_STRICT_SHIFT 29 +#define DPAA2_EQCR_STRICT_MASK 0x00000001 /* ORP ID shift and mask */ #define DPAA2_EQCR_OPRID_SHIFT 16 -#define DPAA2_EQCR_OPRID_MASK 0x00003FFF +#define DPAA2_EQCR_OPRID_MASK 0x00001FFF /* Sequence number shift and mask */ #define DPAA2_EQCR_SEQNUM_SHIFT 0 #define DPAA2_EQCR_SEQNUM_MASK 0x0000FFFF @@ -106,6 +108,35 @@ dpaa2_hw_dump(const char *fmt, ...) #define DPAA2_SEC_SIMPLE_FD_IB_MIN \ ((-SEC_FLC_DHR_INBOUND) + sizeof(void *) * 2) +enum dpaa2_queue_order_type { + DPAA2_QUEUE_NONE_ORDER, + DPAA2_QUEUE_HOLD_ACTIVE_ORDER, + DPAA2_QUEUE_LOOSE_ORP_ORDER, + DPAA2_QUEUE_STRICT_ORP_ORDER +}; + +static inline void +dpaa2_orp_config_helper(struct opr_cfg *ocfg, int strict) +{ + memset(ocfg, 0, sizeof(struct opr_cfg)); + /* Restoration window size = 256 frames */ + ocfg->oprrws = 3; + /* Restoration window size = 512 frames for LX2 */ + if (dpaa2_svr_family == SVR_LX2160A) + ocfg->oprrws = 4; + /* Auto advance NESN window enabled */ + ocfg->oa = 1; + /* Late arrival window size disabled */ + ocfg->olws = 0; + /* ORL resource exhaustion advance NESN disabled */ + ocfg->oeane = 0; + /* Strict ordering enabled(loose ordering disabled) */ + if (strict) + ocfg->oloe = 0; + else + ocfg->oloe = 1; +} + struct dpaa2_queue; #define DPAA2_PORTAL_DEQUEUE_DEPTH 32 @@ -191,6 +222,7 @@ struct __rte_cache_aligned dpaa2_queue { uint32_t fqid; /*!< Unique ID of this queue */ uint16_t flow_id; /*!< To be used by DPAA2 framework */ uint8_t tc_index; /*!< traffic class identifier */ + enum dpaa2_queue_order_type order_type; uint64_t rx_pkts; uint64_t tx_pkts; uint64_t err_pkts; @@ -531,9 +563,10 @@ dpaa2_mem_va_to_iova_check(void *va, uint64_t size) } \ }) -#define dpaa2_mbuf_seq_order_set(mbuf, id, seqnum) \ +#define dpaa2_mbuf_seq_order_set(mbuf, id, seqnum, strict) \ ({ \ *dpaa2_seqn(mbuf) = DPAA2_ENQUEUE_FLAG_ORP; \ + *dpaa2_seqn(mbuf) |= strict << DPAA2_EQCR_STRICT_SHIFT; \ *dpaa2_seqn(mbuf) |= id << DPAA2_EQCR_OPRID_SHIFT; \ *dpaa2_seqn(mbuf) |= seqnum << DPAA2_EQCR_SEQNUM_SHIFT; \ }) @@ -585,12 +618,18 @@ dpaa2_dq_atomic_save(const struct qbman_result *dq, static inline void dpaa2_dq_order_save(const struct qbman_result *dq, - struct rte_mbuf *mbuf) + struct rte_mbuf *mbuf, enum dpaa2_queue_order_type order_type) { + uint32_t strict = order_type == DPAA2_QUEUE_STRICT_ORP_ORDER ? 1 : 0; uint32_t odpid = qbman_result_DQ_odpid(dq); uint32_t seqnum = qbman_result_DQ_seqnum(dq); #ifdef DPAA2_ORDER_DEBUG + if (order_type != DPAA2_QUEUE_LOOSE_ORP_ORDER && + order_type != DPAA2_QUEUE_STRICT_ORP_ORDER) { + dpaa2_hw_dump("Critical! Invalid order type(%d)\n", order_type); + return; + } if (odpid > DPAA2_EQCR_OPRID_MASK) { dpaa2_hw_dump("Critical! too large odp ID(%d)\n", odpid); return; @@ -600,7 +639,7 @@ dpaa2_dq_order_save(const struct qbman_result *dq, return; } #endif - dpaa2_mbuf_seq_order_set(mbuf, odpid, seqnum); + dpaa2_mbuf_seq_order_set(mbuf, odpid, seqnum, strict); } static inline int @@ -662,7 +701,7 @@ dpaa2_enq_rsp_process(struct dpaa2_queue *txq, uint16_t num) static inline int dpaa2_eq_set_order_desc(struct dpaa2_queue *dpaa2_q, struct rte_mbuf *m, - struct qbman_eq_desc *eqdesc, int loose_ordered) + struct qbman_eq_desc *eqdesc) { uint16_t orpid, seqnum, next; int rsp; @@ -672,9 +711,9 @@ dpaa2_eq_set_order_desc(struct dpaa2_queue *dpaa2_q, struct rte_mbuf *m, qbman_eq_desc_set_fq(eqdesc, dpaa2_q->fqid); orpid = (*dpaa2_seqn(m) >> DPAA2_EQCR_OPRID_SHIFT) & DPAA2_EQCR_OPRID_MASK; seqnum = (*dpaa2_seqn(m) >> DPAA2_EQCR_SEQNUM_SHIFT) & DPAA2_EQCR_SEQNUM_MASK; - rsp = loose_ordered ? 0 : 1; + rsp = (*dpaa2_seqn(m) >> DPAA2_EQCR_STRICT_SHIFT) & DPAA2_EQCR_STRICT_MASK; qbman_eq_desc_set_orp(eqdesc, rsp, orpid, seqnum, 0); - if (loose_ordered) { + if (!rsp) { qbman_eq_desc_set_response(eqdesc, 0, 0); goto orp_quit; } @@ -791,7 +830,8 @@ void rte_dpaa2_free_dpci_dev(struct dpaa2_dpci_dev *dpci); __rte_internal int rte_dpaa2_dpci_link_attach(struct dpaa2_dpci_dev *dpci_dev, enum dpci_dest dest_type, uint32_t dest_id, uint8_t priority, - dpaa2_queue_cb_dqrr_t *rx_cb, struct dpaa2_queue **txq); + dpaa2_queue_cb_dqrr_t *rx_cb, enum dpaa2_queue_order_type order_type, + struct dpaa2_queue **txq); /* Global MCP pointer */ __rte_internal diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c index f51c231b99..a88bf0fe8f 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c @@ -1515,7 +1515,6 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, struct qbman_swp *swp; uint16_t num_tx = 0, bpid, frames_to_send, loop; uint8_t dqrr_size[MAX_TX_RING_SLOTS]; - struct dpaa2_sec_dev_private *priv = dpaa2_qp->tx_vq.crypto_data->dev_private; struct rte_mbuf *mbuf[MAX_TX_RING_SLOTS]; uint64_t dqrr_held[MAX_TX_RING_SLOTS]; @@ -1550,7 +1549,7 @@ dpaa2_sec_enqueue_burst_ordered(void *qp, struct rte_crypto_op **ops, dqrr_held[loop] = 0; if (dpaa2_mbuf_seq_is_flag_set(mbuf[loop], DPAA2_ENQUEUE_FLAG_ORP)) { ret = dpaa2_eq_set_order_desc(&dpaa2_qp->tx_vq, mbuf[loop], - &eqdesc[loop], priv->en_loose_ordered); + &eqdesc[loop]); if (ret) goto skip_tx; } else { @@ -4118,7 +4117,7 @@ dpaa2_sec_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, ev->priority = rxq->ev.priority; crypto_op = dpaa2_sec_fd_to_mbuf(fd, qp); - dpaa2_dq_order_save(dq, crypto_op->sym->m_src); + dpaa2_dq_order_save(dq, crypto_op->sym->m_src, qp->rx_vq.order_type); qbman_swp_dqrr_consume(swp, dq); ev->event_ptr = crypto_op; @@ -4135,6 +4134,7 @@ dpaa2_sec_eventq_attach(const struct rte_cryptodev *dev, struct fsl_mc_io *dpseci = (struct fsl_mc_io *)priv->hw; struct dpaa2_sec_qp *qp = dev->data->queue_pairs[qp_id]; struct dpseci_rx_queue_cfg cfg; + struct opr_cfg ocfg; uint8_t priority; int ret; @@ -4158,42 +4158,27 @@ dpaa2_sec_eventq_attach(const struct rte_cryptodev *dev, cfg.options |= DPSECI_QUEUE_OPT_USER_CTX; cfg.user_ctx = (size_t)(&qp->rx_vq); + qp->rx_vq.order_type = DPAA2_QUEUE_NONE_ORDER; if (event->sched_type == RTE_SCHED_TYPE_ATOMIC) { cfg.options |= DPSECI_QUEUE_OPT_ORDER_PRESERVATION; cfg.order_preservation_en = 1; - } - - if (event->sched_type == RTE_SCHED_TYPE_ORDERED) { - struct opr_cfg ocfg; - - /* Restoration window size = 256 frames */ - ocfg.oprrws = 3; - /* Restoration window size = 512 frames for LX2 */ - if (dpaa2_svr_family == SVR_LX2160A) - ocfg.oprrws = 4; - /* Auto advance NESN window enabled */ - ocfg.oa = 1; - /* Late arrival window size disabled */ - ocfg.olws = 0; - /* ORL resource exhaustaion advance NESN disabled */ - ocfg.oeane = 0; - - if (priv->en_loose_ordered) - ocfg.oloe = 1; - else - ocfg.oloe = 0; - + qp->rx_vq.order_type = DPAA2_QUEUE_HOLD_ACTIVE_ORDER; + } else if (event->sched_type == RTE_SCHED_TYPE_ORDERED) { + dpaa2_orp_config_helper(&ocfg, !priv->en_loose_ordered); ret = dpseci_set_opr(dpseci, CMD_PRI_LOW, priv->token, - qp_id, OPR_OPT_CREATE, &ocfg); + qp_id, OPR_OPT_CREATE, &ocfg); if (ret) { DPAA2_SEC_ERR("Error setting opr: ret: %d", ret); return ret; } - priv->en_ordered = 1; + if (priv->en_loose_ordered) + qp->rx_vq.order_type = DPAA2_QUEUE_LOOSE_ORP_ORDER; + else + qp->rx_vq.order_type = DPAA2_QUEUE_STRICT_ORP_ORDER; } ret = dpseci_set_rx_queue(dpseci, CMD_PRI_LOW, priv->token, - qp_id, &cfg); + qp_id, &cfg); if (ret) { DPAA2_SEC_ERR("Error in dpseci_set_queue: ret: %d", ret); return ret; diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h index f29817f456..2995aec943 100644 --- a/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h +++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_priv.h @@ -39,7 +39,6 @@ struct dpaa2_sec_dev_private { uint16_t token; /**< Token required by DPxxx objects */ unsigned int max_nb_queue_pairs; /**< Max number of queue pairs supported by device */ - uint8_t en_ordered; uint8_t en_loose_ordered; enum dpaa2_sec_dump_levels dump_level; }; diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index a03b04a057..011883bba8 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -185,7 +185,7 @@ dpaa2_eventdev_enqueue_burst(void *port, const struct rte_event ev[], if (event->sched_type == RTE_SCHED_TYPE_ORDERED && dpaa2_mbuf_seq_is_flag_set(event->mbuf, DPAA2_ENQUEUE_FLAG_ORP)) { ret = dpaa2_eq_set_order_desc(dpci_txq[loop], event->mbuf, - &eqdesc[loop], true); + &eqdesc[loop]); if (ret) { rte_mempool_put(dpci_txq[loop]->env_pool, ev_tx[loop]); goto send_partial; @@ -304,7 +304,7 @@ static void dpaa2_eventdev_process_order(struct dpaa2_dpio_dev *dpio_dev, struct qbman_swp *swp = dpio_dev->sw_portal; dpaa2_eventdev_rx_get_event(fd, rxq, ev); - dpaa2_dq_order_save(dq, ev->mbuf); + dpaa2_dq_order_save(dq, ev->mbuf, rxq->order_type); qbman_swp_dqrr_consume(swp, dq); } @@ -1319,7 +1319,7 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, dpcon_dev->dpcon_id, 0, - dpaa2_eventdev_process_parallel, + dpaa2_eventdev_process_parallel, DPAA2_QUEUE_NONE_ORDER, &evq_info->dpci_txqs[RTE_SCHED_TYPE_PARALLEL]); if (ret) { DPAA2_EVENTDEV_ERR("DPCI attach parallel qp failed: err(%d)", ret); @@ -1328,7 +1328,7 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, dpcon_dev->dpcon_id, 0, - dpaa2_eventdev_process_atomic, + dpaa2_eventdev_process_atomic, DPAA2_QUEUE_HOLD_ACTIVE_ORDER, &evq_info->dpci_txqs[RTE_SCHED_TYPE_ATOMIC]); if (ret) { DPAA2_EVENTDEV_ERR("DPCI attach atomic qp failed: err(%d)", ret); @@ -1337,7 +1337,7 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, dpcon_dev->dpcon_id, 0, - dpaa2_eventdev_process_order, + dpaa2_eventdev_process_order, DPAA2_QUEUE_LOOSE_ORP_ORDER, &evq_info->dpci_txqs[RTE_SCHED_TYPE_ORDERED]); if (ret) { DPAA2_EVENTDEV_ERR("DPCI attach order qp failed: err(%d)", ret); diff --git a/drivers/event/dpaa2/dpaa2_scheduler.c b/drivers/event/dpaa2/dpaa2_scheduler.c index a80ec05add..325c23e1dc 100644 --- a/drivers/event/dpaa2/dpaa2_scheduler.c +++ b/drivers/event/dpaa2/dpaa2_scheduler.c @@ -158,7 +158,7 @@ dpaa2_scheduler_dpci_recv(struct dpaa2_sch_dev *sch_dev, dpcon_dev = sch_dev->dpcon_dev[cpu]; dpci_dev = sch_dev->dpci_dev[cpu]; ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, - dpcon_dev->dpcon_id, 0, NULL, NULL); + dpcon_dev->dpcon_id, 0, NULL, DPAA2_QUEUE_NONE_ORDER, NULL); if (ret) { DPAA2_EVENTDEV_ERR("DPCI link attaches dpcon failed: err(%d)", ret); return 0; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index b75625dc01..b6e911266f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -113,7 +113,8 @@ dpaa2_dev_args_qos_entries_per_tc(void *vdev, ENTRY("drv_qos_entries_per_tc", dpaa2_dev_args_qos_entries_per_tc, \ DPAA2_QOS_ENTRIES_PER_TC_FLAG) \ ENTRY("drv_qos_flow_only_steer", NULL, DPAA2_QOS_FLOW_ONLY_STEER_FLAG) \ - ENTRY("drv_flow_api_debug", NULL, DPAA2_FLOW_API_DEBUG_FLAG) + ENTRY("drv_flow_api_debug", NULL, DPAA2_FLOW_API_DEBUG_FLAG) \ + ENTRY("drv_queue_strict_order", NULL, DPAA2_QUEUE_STRICT_ORDER_FLAG) #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_REPEAT_TIME 90 /* 9s (90 * 100ms) in total */ @@ -3388,7 +3389,8 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, struct dpaa2_queue *dpaa2_ethq = eth_priv->rx_vq[eth_rx_queue_id]; uint8_t flow_id = dpaa2_ethq->flow_id, options, priority; struct dpni_queue *cfg; - int ret; + struct opr_cfg ocfg; + int ret, strict = false; cfg = dpaa2_ethq->cfg; @@ -3412,35 +3414,15 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, cfg->destination.id = dpcon->dpcon_id; cfg->destination.priority = priority; + dpaa2_ethq->order_type = DPAA2_QUEUE_NONE_ORDER; if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ATOMIC) { options |= DPNI_QUEUE_OPT_HOLD_ACTIVE; cfg->destination.hold_active = 1; - } - - if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED && - !eth_priv->en_ordered) { - struct opr_cfg ocfg; - - /* Restoration window size = 256 frames */ - ocfg.oprrws = 3; - /* Restoration window size = 512 frames for LX2 */ - if (dpaa2_svr_family == SVR_LX2160A) - ocfg.oprrws = 4; - /* Auto advance NESN window enabled */ - ocfg.oa = 1; - /* Late arrival window size disabled */ - ocfg.olws = 0; - /* ORL resource exhaustion advance NESN disabled */ - ocfg.oeane = 0; - /* Loose ordering enabled */ - ocfg.oloe = 1; - eth_priv->en_loose_ordered = 1; - /* Strict ordering enabled if explicitly set */ - if (getenv("DPAA2_STRICT_ORDERING_ENABLE")) { - ocfg.oloe = 0; - eth_priv->en_loose_ordered = 0; - } - + dpaa2_ethq->order_type = DPAA2_QUEUE_HOLD_ACTIVE_ORDER; + } else if (queue_conf->ev.sched_type == RTE_SCHED_TYPE_ORDERED) { + if (eth_priv->flags & DPAA2_QUEUE_STRICT_ORDER_FLAG) + strict = true; + dpaa2_orp_config_helper(&ocfg, strict); ret = dpni_set_opr(dpni, CMD_PRI_LOW, eth_priv->token, dpaa2_ethq->tc_index, flow_id, OPR_OPT_CREATE, &ocfg, 0); if (ret) { @@ -3448,8 +3430,10 @@ int dpaa2_eth_eventq_attach(const struct rte_eth_dev *dev, ret, dpaa2_ethq->tc_index, flow_id); return ret; } - - eth_priv->en_ordered = 1; + if (strict) + dpaa2_ethq->order_type = DPAA2_QUEUE_STRICT_ORP_ORDER; + else + dpaa2_ethq->order_type = DPAA2_QUEUE_LOOSE_ORP_ORDER; } options |= DPNI_QUEUE_OPT_USER_CTX; diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 491ad78d85..33f78d310a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -115,6 +115,8 @@ #define DPAA2_FLOW_API_DEBUG_FLAG RTE_BIT32(16) +#define DPAA2_QUEUE_STRICT_ORDER_FLAG RTE_BIT32(17) + /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -401,8 +403,6 @@ struct dpaa2_dev_priv { uint16_t fs_entries; uint8_t dist_queues; uint8_t num_channels; - uint8_t en_ordered; - uint8_t en_loose_ordered; uint8_t max_cgs; /** RXQs in same TC share same cgid.*/ uint8_t cgid_in_use[MAX_TCS]; diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index fec046deaf..2af5a4745d 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1250,7 +1250,7 @@ dpaa2_dev_process_ordered_event(struct dpaa2_dpio_dev *dpio_dev, else ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); - dpaa2_dq_order_save(dq, ev->mbuf); + dpaa2_dq_order_save(dq, ev->mbuf, rxq->order_type); qbman_swp_dqrr_consume(swp, dq); } @@ -1731,10 +1731,8 @@ dpaa2_dev_tx_multi_txq_ordered(struct dpaa2_queue **dpaa2_q, dqrr_held[loop] = 0; dqrr_size[loop] = 0; - if (dpaa2_mbuf_seq_is_flag_set(bufs[loop], DPAA2_ENQUEUE_FLAG_ORP) && - priv->en_ordered) { - ret = dpaa2_eq_set_order_desc(priv->tx_vq[0], bufs[loop], &eqdesc[loop], - priv->en_loose_ordered); + if (dpaa2_mbuf_seq_is_flag_set(bufs[loop], DPAA2_ENQUEUE_FLAG_ORP)) { + ret = dpaa2_eq_set_order_desc(priv->tx_vq[0], bufs[loop], &eqdesc[loop]); if (ret) goto send_frames; } else { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 63/65] event/dpaa2: support multi-port enqueue in selftest random event generator 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (61 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 62/65] bus/fslmc: make DPAA2 ORP/ODP ordering per-queue instead of per-device Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 64/65] event/dpaa2: do not fail device creation on DPCI errors Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 65/65] net/dpaa2: add Tx fast path for no-confirmation case Prashant Gupta 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 eventdev selftest helper generate_random_events() used to hard-code port 0 both as the only port linked to all queues and as the source port for every enqueued event. That worked for the single-port tests but made it impossible to exercise the multi-port dequeue path correctly: test_multi_queue_enq_multi_port_deq() was enqueuing all events from port 0 while expecting workers on every port to drain them, which does not match how real multi-port setups are configured. Rework the helper and its callers so that ordering/port fan-out is driven by the test, not baked into the generator: - generate_random_events() now takes an array of port ids and a port count. It links the full queue set to each of those ports and round-robins the source port of generated events across them (rte_rand() % nr_ports) instead of always using port 0. - test_multi_queue_enq_single_port_deq() and test_dev_stop_flush() pass a single-element {0} array, preserving their previous behavior. - test_multi_queue_enq_multi_port_deq() queries the device port count (capped at MAX_PORTS), builds the port id array, and only then generates events, so events are actually spread across all ports that workers will dequeue from. Also split the teardown for test_dev_stop_flush: because the stop-flush callback already frees mbufs back to the pool, calling the standard eventdev_teardown() (which does extra cleanup assuming a live mempool state) was fragile. Introduce eventdev_stop_flush_teardown() that only frees the mempool, and wire it into the DPAA2_TEST_RUN entry for test_dev_stop_flush. No functional change for the single-port tests; the multi-port test now actually tests multi-port enqueue + multi-port dequeue. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev_selftest.c | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev_selftest.c b/drivers/event/dpaa2/dpaa2_eventdev_selftest.c index 569621dc39..6162932a5c 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev_selftest.c +++ b/drivers/event/dpaa2/dpaa2_eventdev_selftest.c @@ -227,6 +227,12 @@ eventdev_teardown(void) rte_mempool_free(eventdev_test_mempool); } +static void +eventdev_stop_flush_teardown(void) +{ + rte_mempool_free(eventdev_test_mempool); +} + static void update_event_and_validation_attr(struct rte_mbuf *m, struct rte_event *ev, uint32_t flow_id, uint8_t event_type, @@ -305,7 +311,8 @@ check_excess_events(uint8_t port) } static int -generate_random_events(const unsigned int total_events) +generate_random_events(const uint32_t total_events, + uint8_t port_ids[], uint32_t nr_ports) { struct rte_event_dev_info info; uint32_t queue_count, i; @@ -320,10 +327,11 @@ generate_random_events(const unsigned int total_events) for (i = 0; i < queue_count; i++) queues[i] = i; - ret = rte_event_port_link(evdev, 0, queues, NULL, - queue_count); - RTE_TEST_ASSERT(ret >= 0, "Failed to link %d queues port0", - queue_count); + for (i = 0; i < nr_ports; i++) { + ret = rte_event_port_link(evdev, port_ids[i], queues, NULL, queue_count); + RTE_TEST_ASSERT(ret >= 0, "Failed to link %d queues port.%d", + queue_count, port_ids[i]); + } ret = rte_event_dev_info_get(evdev, &info); RTE_TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info"); @@ -333,7 +341,7 @@ generate_random_events(const unsigned int total_events) rte_rand() % 256 /* sub_event_type */, rte_rand() % (RTE_SCHED_TYPE_PARALLEL + 1), rte_rand() % queue_count, - 0 /* port */, + rte_rand() % nr_ports, 1 /* events */); if (ret) return ret; @@ -341,7 +349,6 @@ generate_random_events(const unsigned int total_events) return ret; } - static int validate_event(struct rte_event *ev) { @@ -475,8 +482,9 @@ test_multi_queue_enq_single_port_deq(void) { int ret; uint32_t dq_events; + uint8_t port_id = 0; - ret = generate_random_events(MAX_EVENTS); + ret = generate_random_events(MAX_EVENTS, &port_id, 1); if (ret) return ret; @@ -608,13 +616,10 @@ static int test_multi_queue_enq_multi_port_deq(void) { const unsigned int total_events = MAX_EVENTS; - uint32_t nr_ports; + uint32_t nr_ports, i; + uint8_t port_ids[MAX_PORTS]; int ret; - ret = generate_random_events(total_events); - if (ret) - return ret; - RTE_TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_PORT_COUNT, &nr_ports), "Port count get failed"); @@ -625,6 +630,14 @@ test_multi_queue_enq_multi_port_deq(void) __func__, nr_ports, rte_lcore_count() - 1); return -EINVAL; } + if (nr_ports > MAX_PORTS) + nr_ports = MAX_PORTS; + + for (i = 0; i < nr_ports; i++) + port_ids[i] = i; + ret = generate_random_events(total_events, port_ids, nr_ports); + if (ret) + return ret; return launch_workers_and_wait(worker_multi_port_fn, worker_multi_port_fn, total_events, @@ -646,8 +659,9 @@ test_dev_stop_flush(void) { unsigned int total_events = MAX_EVENTS, count = 0; int ret; + uint8_t port_id = 0; - ret = generate_random_events(total_events); + ret = generate_random_events(total_events, &port_id, 1); if (ret) return -1; @@ -861,7 +875,7 @@ test_eventdev_dpaa2(void) test_simple_enqdeq_parallel); DPAA2_TEST_RUN(eventdev_setup, eventdev_teardown, test_multi_queue_enq_single_port_deq); - DPAA2_TEST_RUN(eventdev_setup, eventdev_teardown, + DPAA2_TEST_RUN(eventdev_setup, eventdev_stop_flush_teardown, test_dev_stop_flush); DPAA2_TEST_RUN(eventdev_atomic_port_setup, eventdev_teardown, test_multi_queue_enq_multi_port_deq); -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 64/65] event/dpaa2: do not fail device creation on DPCI errors 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (62 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 63/65] event/dpaa2: support multi-port enqueue in selftest random event generator Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 65/65] net/dpaa2: add Tx fast path for no-confirmation case Prashant Gupta 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Event device creation aborted entirely whenever a DPCI object could not be allocated for an event queue, or when any of the parallel, atomic or ordered link attaches failed. A single failure rolled back every queue and made dpaa2_eventdev_create() return an error. This is too strict. The DPNI and DPSEC event adapters can still be registered and used even when the DPCI-backed event queues are not available, so a DPCI shortage or attach failure must not bring the whole event device down. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/event/dpaa2/dpaa2_eventdev.c | 68 +++++++++++++--------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/drivers/event/dpaa2/dpaa2_eventdev.c b/drivers/event/dpaa2/dpaa2_eventdev.c index 011883bba8..5c36cb9dc9 100644 --- a/drivers/event/dpaa2/dpaa2_eventdev.c +++ b/drivers/event/dpaa2/dpaa2_eventdev.c @@ -1278,14 +1278,13 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) struct dpaa2_dpcon_dev *dpcon_dev = NULL; struct dpaa2_dpci_dev *dpci_dev = NULL; struct dpaa2_eventq *evq_info; - int ret = 0, i; + int ret, i, success; eventdev = rte_event_pmd_vdev_init(name, sizeof(struct dpaa2_eventdev), rte_socket_id(), vdev); if (!eventdev) { - ret = -ENOMEM; DPAA2_EVENTDEV_ERR("Failed to create Event device %s", name); - goto done; + return -ENOMEM; } eventdev->dev_ops = &dpaa2_eventdev_ops; @@ -1312,66 +1311,61 @@ dpaa2_eventdev_create(const char *name, struct rte_vdev_device *vdev) dpci_dev = rte_dpaa2_alloc_dpci_dev(); if (!dpci_dev) { - rte_dpaa2_free_dpcon_dev(dpcon_dev); - break; + DPAA2_EVENTDEV_WARN("No dpci available for evq.%d", i); + goto skip_dpci_attach; } - evq_info->dpci = dpci_dev; + success = 0; ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, dpcon_dev->dpcon_id, 0, dpaa2_eventdev_process_parallel, DPAA2_QUEUE_NONE_ORDER, &evq_info->dpci_txqs[RTE_SCHED_TYPE_PARALLEL]); - if (ret) { - DPAA2_EVENTDEV_ERR("DPCI attach parallel qp failed: err(%d)", ret); - goto err_break; - } + if (ret) + DPAA2_EVENTDEV_WARN("DPCI attach parallel qp failed: err(%d)", ret); + else + success++; ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, dpcon_dev->dpcon_id, 0, dpaa2_eventdev_process_atomic, DPAA2_QUEUE_HOLD_ACTIVE_ORDER, &evq_info->dpci_txqs[RTE_SCHED_TYPE_ATOMIC]); - if (ret) { - DPAA2_EVENTDEV_ERR("DPCI attach atomic qp failed: err(%d)", ret); - goto err_break; - } + if (ret) + DPAA2_EVENTDEV_WARN("DPCI attach atomic qp failed: err(%d)", ret); + else + success++; ret = rte_dpaa2_dpci_link_attach(dpci_dev, DPCI_DEST_DPCON, dpcon_dev->dpcon_id, 0, dpaa2_eventdev_process_order, DPAA2_QUEUE_LOOSE_ORP_ORDER, &evq_info->dpci_txqs[RTE_SCHED_TYPE_ORDERED]); - if (ret) { - DPAA2_EVENTDEV_ERR("DPCI attach order qp failed: err(%d)", ret); - goto err_break; - } + if (ret) + DPAA2_EVENTDEV_WARN("DPCI attach order qp failed: err(%d)", ret); + else + success++; + + if (success) + evq_info->dpci = dpci_dev; + else + rte_dpaa2_free_dpci_dev(dpci_dev); +skip_dpci_attach: evq_info->valid = true; evq_info->event_queue_id = priv->max_event_queues; priv->max_event_queues++; - continue; -err_break: - if (evq_info->dpcon) - rte_dpaa2_free_dpcon_dev(evq_info->dpcon); - if (evq_info->dpci) - rte_dpaa2_free_dpci_dev(evq_info->dpci); - break; } done: - if (ret && priv) { - for (i = 0; i < priv->max_event_queues; i++) { - evq_info = &priv->evq_info[i]; - if (evq_info->dpcon) - rte_dpaa2_free_dpcon_dev(evq_info->dpcon); - if (evq_info->dpci) - rte_dpaa2_free_dpci_dev(evq_info->dpci); - } - } + ret = 0; event_dev_probing_finish(eventdev); - if (ret) - DPAA2_EVENTDEV_ERR("Failed(%d) to create event device(%s)", ret, name); - else + if (priv && !priv->max_event_queues) { + ret = -ENODEV; + DPAA2_EVENTDEV_ERR("Failed to create event device(%s)", name); + } else if (rte_eal_process_type() == RTE_PROC_PRIMARY) { DPAA2_EVENTDEV_INFO("Create event device(%s)", name); + } else { + DPAA2_EVENTDEV_INFO("Attach event device(%s)", name); + } return ret; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S3 65/65] net/dpaa2: add Tx fast path for no-confirmation case 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta ` (63 preceding siblings ...) 2026-10-23 13:43 ` [PATCH v4-S3 64/65] event/dpaa2: do not fail device creation on DPCI errors Prashant Gupta @ 2026-10-23 13:43 ` Prashant Gupta 64 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-23 13:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Split a dedicated Tx fast path out of dpaa2_dev_tx() for the common no-confirmation configuration, keeping the hot enqueue loop free of the Tx-conf and timestamp bookkeeping needed only by the slow path. - Add dpaa2_dev_tx_fast() for the DPAA2_TX_NO_CONF case. dpaa2_dev_tx() builds the enqueue descriptor and dispatches straight to it, so the common path no longer runs the per-burst Tx-conf drain or the per-packet timestamp accounting. - Factor the retry enqueue loop into dpaa2_dev_tx_enqueue_multiple() and the ordered-queue tail into dpaa2_dev_tx_multi_ordered(), shared by both the fast and slow paths to remove duplicated code. - Zero-initialise fd_arr in the slow path and mark the rarely taken branches (congestion retry, VLAN insert, ordered, timestamp) unlikely. This reduces per-packet work on the common Tx path. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_rxtx.c | 158 +++++++++++++++++++++++++-------- 1 file changed, 122 insertions(+), 36 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 2af5a4745d..312c9bd7d5 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -1511,6 +1511,114 @@ dpaa2_dev_tx_ordered(void *queue, struct rte_mbuf **bufs, return dpaa2_dev_tx_multi_txq_ordered(mq, bufs, nb_pkts); } +static __rte_always_inline uint16_t __rte_hot +dpaa2_dev_tx_enqueue_multiple(struct qbman_swp *swp, + const struct qbman_fd *fd, uint16_t to_send, + const struct qbman_eq_desc *eqdesc) +{ + uint16_t loop = 0, retry_count = 0; + int eq_ret; + + while (loop < to_send) { + eq_ret = qbman_swp_enqueue_multiple(swp, eqdesc, + &fd[loop], NULL, to_send - loop); + if (unlikely(eq_ret < 0)) { + retry_count++; + if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) + break; + } else { + loop += eq_ret; + retry_count = 0; + } + } + + return loop; +} + +static __rte_noinline uint16_t +dpaa2_dev_tx_multi_ordered(struct dpaa2_queue *dpaa2_q, + struct rte_mbuf **bufs, uint16_t nb_pkts) +{ + uint16_t to_send, order_tx = 0, total = 0; + +order_tx_again: + to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; + order_tx = dpaa2_dev_tx_ordered(dpaa2_q, bufs, to_send); + bufs += order_tx; + nb_pkts -= order_tx; + total += order_tx; + if (nb_pkts && order_tx >= to_send) + goto order_tx_again; + + return total; +} + +static __rte_always_inline uint16_t __rte_hot +dpaa2_dev_tx_fast(struct dpaa2_queue *dpaa2_q, struct rte_mbuf **bufs, + uint16_t nb_pkts, struct qbman_swp *swp, struct qbman_fd *fd_arr, + const struct qbman_eq_desc *eqdesc, struct rte_mempool *hw_mp) +{ + /* Function to transmit the frames to given device and VQ*/ + uint32_t loop, retry_count, frames_to_send; + int32_t ret, order = false; + uint16_t num_tx = 0, eq_ret = 0; + +tx_again: + /*Check if the queue is congested*/ + retry_count = 0; + while (qbman_result_SCN_state(dpaa2_q->cscn)) { + retry_count++; + /* Retry for some time before giving up */ + if (retry_count > CONG_RETRY_COUNT) + goto skip_tx; + } + + frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; + + for (loop = 0; loop < frames_to_send; loop++) { + if (unlikely(dpaa2_mbuf_seq_is_flag_set((*bufs), + (DPAA2_ENQUEUE_FLAG_ORP | QBMAN_ENQUEUE_FLAG_DCA)))) { + order = true; + break; + } + + if (unlikely((*bufs)->ol_flags & RTE_MBUF_F_TX_VLAN)) { + ret = rte_vlan_insert(bufs); + if (ret) + break; + } + if (likely(RTE_MBUF_DIRECT(*bufs) && + (*bufs)->pool->ops_index == hw_mp->ops_index && + (*bufs)->nb_segs == 1 && rte_mbuf_refcnt_read(*bufs) == 1)) { + DPAA2_MBUF_TO_CONTIG_FD((*bufs), &fd_arr[loop], + mempool_to_bpid((*bufs)->pool)); + ret = 0; + } else if (unlikely((*bufs)->nb_segs > 1)) { + ret = dpaa2_dev_tx_mbuf_to_sg_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, DPAA2_TX_NO_CONF, false); + } else { + ret = dpaa2_dev_tx_mbuf_to_simple_fd(hw_mp, *bufs, &fd_arr[loop], + dpaa2_q, DPAA2_TX_NO_CONF, false); + } + if (ret) + break; + bufs++; + } + + eq_ret = dpaa2_dev_tx_enqueue_multiple(swp, fd_arr, loop, eqdesc); + num_tx += eq_ret; + nb_pkts -= eq_ret; + if (unlikely(nb_pkts > 0 && !ret && !order)) + goto tx_again; + +skip_tx: + dpaa2_q->tx_pkts += num_tx; + if (unlikely(order && eq_ret >= loop)) + num_tx += dpaa2_dev_tx_multi_ordered(dpaa2_q, bufs, nb_pkts); + + return num_tx; +} + /* * Callback to handle sending packets through WRIOP based interface */ @@ -1519,12 +1627,12 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { /* Function to transmit the frames to given device and VQ*/ uint32_t loop, retry_count, i, ptp_n, frames_to_send; - int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set, order = false, eq_ret = 0; - struct qbman_fd fd_arr[MAX_TX_RING_SLOTS]; + int32_t ret, tstamp[MAX_TX_RING_SLOTS], ptp_set, order = false; + struct qbman_fd fd_arr[MAX_TX_RING_SLOTS] = {0}; struct qbman_eq_desc eqdesc; struct dpaa2_queue *dpaa2_q = queue; struct qbman_swp *swp; - uint16_t num_tx = 0, order_tx; + uint16_t num_tx = 0, eq_ret = 0; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; struct rte_mempool *hw_mp; @@ -1549,15 +1657,15 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } hw_mp = priv->bp_list->mp; - if (dpaa2_q->tx_conf_queue) - dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue, false); - /*Prepare enqueue descriptor*/ qbman_eq_desc_clear(&eqdesc); qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ); qbman_eq_desc_set_fq(&eqdesc, dpaa2_q->fqid); + if (likely(priv->tx_conf_type == DPAA2_TX_NO_CONF)) + return dpaa2_dev_tx_fast(dpaa2_q, bufs, nb_pkts, swp, fd_arr, &eqdesc, hw_mp); - /*Clear the unused FD fields before sending*/ + if (dpaa2_q->tx_conf_queue) + dpaa2_dev_tx_conf(dpaa2_q->tx_conf_queue, false); tx_again: /*Check if the queue is congested*/ @@ -1617,27 +1725,13 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) bufs++; } - frames_to_send = loop; - loop = 0; - retry_count = 0; - while (loop < frames_to_send) { - eq_ret = qbman_swp_enqueue_multiple(swp, &eqdesc, - &fd_arr[loop], NULL, frames_to_send - loop); - if (unlikely(eq_ret < 0)) { - retry_count++; - if (retry_count > DPAA2_MAX_TX_RETRY_COUNT) - break; - } else { - loop += eq_ret; - retry_count = 0; - } - } + eq_ret = dpaa2_dev_tx_enqueue_multiple(swp, fd_arr, loop, &eqdesc); + num_tx += eq_ret; + nb_pkts -= eq_ret; - num_tx += loop; - nb_pkts -= loop; if (priv->tx_conf_type != DPAA2_TX_NO_CONF) { - for (i = 0; i < loop; i++) { - if (tstamp[i]) { + for (i = 0; i < eq_ret; i++) { + if (unlikely(tstamp[i])) { rte_atomic_fetch_add_explicit(&dpaa2_q->tx_conf_queue->ts_to_cnfd, 1, rte_memory_order_relaxed); } @@ -1648,16 +1742,8 @@ dpaa2_dev_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) skip_tx: dpaa2_q->tx_pkts += num_tx; - if (order && eq_ret >= 0) { -order_tx_again: - frames_to_send = (nb_pkts > dpaa2_eqcr_size) ? dpaa2_eqcr_size : nb_pkts; - nb_pkts -= frames_to_send; - order_tx = dpaa2_dev_tx_ordered(queue, bufs, frames_to_send); - num_tx += order_tx; - bufs += frames_to_send; - if (nb_pkts && order_tx >= frames_to_send) - goto order_tx_again; - } + if (unlikely(order && eq_ret >= loop)) + num_tx += dpaa2_dev_tx_multi_ordered(dpaa2_q, bufs, nb_pkts); return num_tx; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (13 preceding siblings ...) 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta @ 2026-09-15 15:42 ` Stephen Hemminger 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta 15 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-15 15:42 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Tue, 15 Sep 2026 17:04:46 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This is the second of four series upstreaming the missing NXP dpaa2 > driver changes. It does not depend on series 1 and can be applied > independently. It adds the net/dpaa2 flow, metering and parser features: > > - fix an integer overflow in the CCSR region mapping, > - set Tx confirmation on device init and support a larger burst size, > - support MPLS and PPPoE flow distribution, meter and policing, and the > flow drop action, with a per-device default flow miss action, > - identify Rx mbuf hash information by FLC and add minimum key size > support, > - restructure the parser processing, parse tunnel and fragmented packet > types, remove the unused soft parser driver and rename the Rx queue > flags. > > Every commit builds cleanly (including the aarch64 DPAA cross build with > -Werror) and the series is bisectable. AI review with Opus found lots of issues that still need to be fixed. Series: [PATCH v3-S2 00/13] net/dpaa2 flow, meter, parser rework Patch 10 claims no functional change but rewrites the Rx path and introduces mbuf memory corruption on every received packet. Patches 5 and 7 have functional problems of their own. Not ready. All 13 commits apply to main and build with -Dwerror=true (default config, RTE_LIBRTE_IEEE1588 off). ---------------------------------------------------------------------- Patch 01/13 net/dpaa2: fix integer overflow in CCSR region mapping Warning PAGE_SIZE and PAGE_MASK (dpaa2_recycle.c:32-35) have no users after this patch. Remove them. Info (pre-existing, not introduced here) lsx_ccsr_map_region() rounds len down with page_mask and does not add offset to the mapped length, so a region crossing a page boundary is only partially mapped. The mapping is never unmapped. ---------------------------------------------------------------------- Patch 03/13 net/dpaa2: support larger burst size Warning The non-LX2160A limit drops from DPAA2_BURST_MAX (65536) to 0xF7FF. The old value was broken anyway: max_burst_size was uint16_t, so 65536 truncated to 0. Say both in the commit message; the truncation is a stable fix on its own. Warning return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; The header comment documents this as 0x37FFF. Use hex in both places, and name the 8.7 version like the existing DPNI_GET_MAC_SUPPORTED_IFS_VER_* defines. Info DPNI_BURST_LO/HI describe the MC command layout and belong in fsl_dpni_cmd.h rather than fsl_dpni.h. ---------------------------------------------------------------------- Patch 04/13 net/dpaa2: support MPLS and PPPoE flow distribution Warning mask = pattern->mask ? pattern->mask : &dpaa2_flow_item_mpls_mask; The driver default is { 0xff, 0xff, 0xff }, covering TC and the bottom-of-stack bit. rte_flow defines a NULL mask as the item default (label only). A spec with only the label set does not match single-label packets (S=1). Warning Every MPLS item extracts NH_FLD_MPLS_MPLSL_1. For eth / mpls / mpls the second item overwrites the first label's key data instead of matching label 2. Reject a second MPLS item or map it to MPLSL_2 / MPLSL_N. Info Extra blank line added after the #endif of the mask block. ---------------------------------------------------------------------- Patch 05/13 net/dpaa2: support meter and policing Error The meter ops only maintain software lists. Nothing calls dpni_set_rx_tc_policing(), and dpaa2_flow.c has no RTE_FLOW_ACTION_TYPE_METER handling. Creating a meter has no effect on traffic, while capabilities, dpaa2.rst, dpaa2.ini and the release notes advertise metering and policing. Error dpni_set_rx_tc_policing_v1() is declared in fsl_dpni.h and defined nowhere. DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS and DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS are unused. Warning s_dpaa2_mtr_capa is file-scope and written under priv->meter_lock. The lock is per port, so two ports race on the shared struct. Fill the caller's capa directly. Warning static char s_err_msg[128] is shared across ports and threads and handed back through rte_mtr_error. Concurrent failures overwrite each other's message. Warning dpaa2_mtr_profile_add() and dpaa2_mtr_policy_add() accept a duplicate id; the new entry is appended and lookups return the first. Warning Profiles, policies and meters are never freed on dev_close. priv->profiles, priv->policies and priv->meters are referenced only in dpaa2_meter.c. Warning rte_zmalloc() for control-path bookkeeping. Use malloc/calloc. Warning The release note hunk adds "Tx queue based flow control and confirmation queue handling" and "software parser based packet dump", neither of which is in this patch; patch 12 removes the soft parser. Each patch should carry only its own note. ---------------------------------------------------------------------- Patch 07/13 net/dpaa2: set default flow miss action per device Error priv->default_flow = RTE_MIN(priv->fs_entries, priv->dist_queues) - 1; fs_miss_flow_id is a queue id within the TC. fs_entries is the FS table size and has nothing to do with it. The miss queue also moves from 0 to the last hardware queue of the TC. dev_info reports max_rx_queues = priv->nb_rx_queues, so an application that configures fewer queues never sets up or polls that queue and loses every unmatched frame. Queue 0 is always configured. With fs_entries == 0 the value becomes 0xffff, which is DPNI_FS_MISS_DROP. Warning The commit message calls this the "lowest priority flow". The field is a queue id, not a priority. ---------------------------------------------------------------------- Patch 08/13 net/dpaa2: identify Rx mbuf hash information by FLC Warning rte_mbuf_sched_set(m, flow, tc, 0) together with RTE_MBUF_F_RX_FDIR. hash.sched is the Tx scheduler field; RX_FDIR tells applications to read hash.fdir from the same union. Use hash.fdir.hi with RTE_MBUF_F_RX_FDIR_ID, or implement RTE_FLOW_ACTION_TYPE_MARK. Warning The FS action sets DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL with data stashing on every SoC. dpaa2_dev_rx_queue_setup() skips FLC/stashing on SVR_LS2080A; the FS path must follow the same rule. Info The QUEUE action index is checked against MAX_RX_QUEUES and rx_vq[] != NULL, not against dev->data->nb_rx_queues, so an unconfigured hardware queue is accepted. ---------------------------------------------------------------------- Patch 09/13 net/dpaa2: add minimum key size support Warning Removes "Current MC only support fixed entry size(56)" and starts using 24-byte entries with no MC/DPNI version check. State the minimum firmware in the commit message and gate it with dpaa2_dev_cmp_dpni_ver(), or older MC rejects the table setup. ---------------------------------------------------------------------- Patch 10/13 net/dpaa2: restructure dpaa2 parser processing Error if (priv->psr_dynfield_offset >= 0) dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); psr_dynfield_offset is never assigned anywhere in the driver. With zeroed dev_private the test is true for every packet, and dpaa2_dev_rx_parse_offset() writes the l3/l4/l5 offsets at (uint8_t *)mbuf + 0, i.e. into buf_addr. The RTE_ASSERT guarding it is compiled out in release builds. Affects dpaa2_dev_prefetch_rx_common(), dpaa2_dev_rx_common() and dump_err_pkts(). Error dpaa2_timestamp_dynfield() is removed, but dpaa2_dev_rx_common() still calls it under #if defined(RTE_LIBRTE_IEEE1588). The build breaks with IEEE1588 enabled. Error Rx timestamp handling is removed from dpaa2_dev_rx_parse() and dpaa2_dev_rx_parse_new(). dpaa2_enable_ts[] is still set in dpaa2_dev_configure() but never read, so RTE_ETH_RX_OFFLOAD_TIMESTAMP silently stops working. The IEEE1588 priv->rx_timestamp update in dpaa2_dev_prefetch_rx_common() is also gone. Error Checksum flag handling is removed from dpaa2_dev_rx_parse() and now exists only in dpaa2_dev_rx_parse_slow(). On non-LX2160A SoCs the fast-path return (word3 test false) no longer reports RX_IP_CKSUM_* or RX_L4_CKSUM_*. Error The "if (!by_channel)" guard around dump_err_pkts() is removed from dpaa2_dev_prefetch_rx_common(). The removed comment explains that the channel/interrupt path owns the ethrx portal, and dpaa2_dev_rx_common() still keeps the guard. This reverts that fix. Error The commit message says no functional change is intended. Also changed: - DPAA2_PKT_TYPE_IPV4_EXT 0x0001 -> 0x0040, IPV6_EXT 0x0021 -> 0x0050 - VLAN_1/VLAN_2 0x0160/0x0260 -> 0x0100/0x0200 - new VLAN TCI reporting (RTE_MBUF_F_RX_VLAN) - event and eqresp paths now handle SG frames - IPv4/IPv6 EXT, SCTP and ICMP dropped from the LX2 fast switch - parser result no longer printed for error-queue frames - hash.sched.color now set from DPAA2_GET_FD_DROPP() on FS frames Split into the header move plus separate functional patches, each with its own justification. Warning dpaa2_dev_rx_print_parser_result() loops i < MAX_RX_QUEUES and dereferences priv->rx_vq[i]->tc_index; entries past priv->nb_rx_queues are NULL. The function is unreachable today because DPAA2_RX_PRINT_PSR_RESULT_FLAG is never set, while dpaa2_dev_init() still sets dpaa2_print_parser_result from getenv() and nothing reads it. The parser debug print is broken either way. Warning Leftovers: rx_ts_offset, rx_ts_flag and L3/L4/L5_OFFSET_OF_MBUF_DYN are unused. sp_protocol is never set, so the fafe2/fafe3 GENEVE branch in dpaa2_dev_rx_parse_new() is dead. dpaa2_dev_rx_parse_new() does RTE_SET_USED(priv) and then uses priv. ---------------------------------------------------------------------- Patch 11/13 net/dpaa2: parse tunnel and fragmented packet types Warning The commit message says the new types are mapped "in the slow-path parser". They are added only to the LX2160A FRC switch in dpaa2_dev_rx_parse_new(); dpaa2_dev_rx_parse() for other SoCs is unchanged. Warning DPAA2_PKT_TYPE_IPV4_FRAG and IPV6_FRAG evaluate to 0x0001 and 0x0021, the values the driver reported as RTE_PTYPE_L3_IPV4_EXT and L3_IPV6_EXT before patch 10. Fragments were misreported as IP options. That is a bug fix for released code and should be a separate patch with Fixes: and Cc: stable@dpdk.org. ---------------------------------------------------------------------- Patch 12/13 net/dpaa2: remove unused soft parser driver Warning dpaa2_soft_parser_loaded() is still defined in dpaa2_flow.c and declared in dpaa2_ethdev.h with no callers, and it still opens /dev/mem. Remove it together with dpaa2_sp_loaded. Warning The commit message is one sentence. Explain what users lose and why runtime loading is unsupported. ---------------------------------------------------------------------- Patch 13/13 net/dpaa2: rename Rx queue flags Info The commit message refers to "the Tx confirmation rework that follows", but this is the last patch in the series. Info The rename should come before patch 10, which adds DPAA2_RX_PRINT_PSR_RESULT_FLAG next to the old DPAAX_ name. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v4-S2 00/13] net/dpaa2: flow, meter and parser features 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (14 preceding siblings ...) 2026-09-15 15:42 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (14 more replies) 15 siblings, 15 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev This is the second of four series upstreaming the missing NXP dpaa2 driver changes. It does not depend on series 1 and can be applied independently. It adds the net/dpaa2 flow, metering and parser features: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, meter and policing, and the flow drop action, with a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - restructure the parser processing, parse tunnel and fragmented packet types, remove the unused soft parser driver and rename the Rx queue flags. Every commit builds cleanly (including the aarch64 DPAA cross build with -Werror) and the series is bisectable. Gagandeep Singh (7): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (4): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 3 + doc/guides/rel_notes/release_26_11.rst | 4 + drivers/net/dpaa2/dpaa2_ethdev.c | 84 +- drivers/net/dpaa2/dpaa2_ethdev.h | 227 +++- drivers/net/dpaa2/dpaa2_flow.c | 397 ++++-- drivers/net/dpaa2/dpaa2_meter.c | 637 ++++++++++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1542 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_recycle.c | 40 +- drivers/net/dpaa2/dpaa2_rxtx.c | 334 +++-- drivers/net/dpaa2/dpaa2_sparser.c | 137 -- drivers/net/dpaa2/dpaa2_sparser.h | 202 --- drivers/net/dpaa2/dpaa2_tm.c | 17 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 11 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 6 +- drivers/net/dpaa2/meson.build | 2 +- 19 files changed, 2999 insertions(+), 1097 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v4-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (13 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is defined as sysconf(_SC_PAGESIZE) which may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). Use sysconf() explicitly with a signed long, check for errors, and compute map_len separately with unsigned arithmetic before passing to mmap. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 39 ++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..ef7caa5f19 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -30,11 +30,6 @@ #include <unistd.h> #include <sys/mman.h> -#ifndef PAGE_SIZE -#define PAGE_SIZE (sysconf(_SC_PAGESIZE)) -#endif -#define PAGE_MASK (~(PAGE_SIZE - 1)) - #define LSX_SERDES_LAN_NB 8 #define LSX_SERDES_REG_BASE 0x1ea0000 #define LSX_LB_EN_BIT 0x10000000 @@ -176,6 +171,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +181,35 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + len = len & page_mask; + if (len == 0) { + close(fd); + return NULL; + } - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + map_len = len; + if (map_len < (size_t)page_size) + map_len = (size_t)page_size; + + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) { + DPAA2_PMD_ERR("mmap 0x%" PRIx64 "(size=0x%zx) failed", + addr, map_len); return NULL; + } + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 02/13] net/dpaa2: set Tx confirmation on device init 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta ` (12 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f211357919..c95704d4ca 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3624,6 +3599,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 03/13] net/dpaa2: support larger burst size 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (11 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_tm.c | 17 ++++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 5 +++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 6 +++++- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..bec1096850 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -462,6 +462,8 @@ struct dpaa2_dev_priv { #define DPNI_GET_MAC_SUPPORTED_IFS_VER_MAJOR 8 #define DPNI_GET_MAC_SUPPORTED_IFS_VER_MINOR 6 +#define DPNI_TX_BURST_LARGE_VER_MAJOR 8 +#define DPNI_TX_BURST_LARGE_VER_MINOR 7 static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, uint16_t ver_major, uint16_t ver_minor) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..0275c2a010 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,21 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, DPNI_TX_BURST_LARGE_VER_MAJOR, + DPNI_TX_BURST_LARGE_VER_MINOR) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 0x37FFF : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +290,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +300,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..7bcbad6859 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -833,11 +833,12 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..cc7bf42a4e 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -391,10 +391,14 @@ struct dpni_rsp_get_link_state { #define DPNI_LNI_SHAPER_SHIFT 1 #define DPNI_LNI_SHAPER_SIZE 1 +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (2 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta ` (10 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 202 ++++++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..63bbce0ab7 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,6 +182,14 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xf0 }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif #define DPAA2_FLOW_DUMP printf @@ -1764,6 +1774,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4059,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4549,7 +4724,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, { const struct rte_flow_action_rss *rss_conf; int is_keycfg_configured = 0, end_of_list = 0; - int ret = 0, i = 0, j = 0; + int ret = 0, i = 0, j = 0, mpls_count = 0; struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_dev_flow *curr = LIST_FIRST(&priv->flows); uint16_t dist_size, key_size; @@ -4712,6 +4887,31 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + if (mpls_count > 0) { + ret = -ENOTSUP; + goto end_flow_set; + } + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + mpls_count++; + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 05/13] net/dpaa2: support meter and policing 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (3 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta ` (9 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API to the dpaa2 PMD. The implementation registers the rte_mtr operations through the ".mtr_ops_get" dev_ops hook and maintains software bookkeeping of meter profiles, policies and meter objects under a per-device spinlock. Supported algorithms are trTCM RFC 2698 and trTCM RFC 4115 in both byte and packet modes. Meter policies support drop and pass-through actions on the red color. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 1 + doc/guides/rel_notes/release_26_11.rst | 4 + drivers/net/dpaa2/dpaa2_ethdev.c | 3 + drivers/net/dpaa2/dpaa2_ethdev.h | 30 ++ drivers/net/dpaa2/dpaa2_meter.c | 637 +++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 6 +- drivers/net/dpaa2/meson.build | 1 + 8 files changed, 680 insertions(+), 3 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index ae8b32af2c..faee3a72a2 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -407,6 +407,7 @@ Features of the DPAA2 PMD are: - Link flow control - Scattered and gather for TX and RX - Rx queue interrupts +- Traffic metering and policing - :ref:`dpaa2_dptmapi` diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..4936769191 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -19,6 +19,7 @@ RSS hash = Y RSS reta update = Y VLAN filter = Y Flow control = Y +Rate limitation = Y Traffic manager = Y VLAN offload = Y L3 checksum offload = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index c8cc86295d..794fa301c1 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -55,6 +55,10 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Updated NXP DPAA2 net driver.** + + * Added support for flow classification on more protocol fields. + * Added support for traffic metering and policing. Removed Items ------------- diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c95704d4ca..8290bbfe91 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1666,6 +1666,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) dpaa2_tm_deinit(dev); dpaa2_flow_clean(dev); + dpaa2_meter_clean(dev); /* Clean the device first */ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); if (ret) { @@ -3320,6 +3321,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, @@ -3543,6 +3545,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->num_channels = attr.num_channels; priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index bec1096850..706b956e71 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + bool red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -411,6 +435,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -456,6 +481,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -533,6 +561,7 @@ uint16_t dpaa2_dev_tx_multi_txq_ordered(void **queue, void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, struct dpaa2_queue *dpaa2_q); void dpaa2_flow_clean(struct rte_eth_dev *dev); +void dpaa2_meter_clean(struct rte_eth_dev *dev); uint16_t dpaa2_dev_tx_conf(void *queue) __rte_unused; int dpaa2_timesync_enable(struct rte_eth_dev *dev); @@ -550,6 +579,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..1824f52c82 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,637 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + memset(capa, 0, sizeof(*capa)); + capa->color_aware_trtcm_rfc2698_supported = true; + capa->color_aware_trtcm_rfc4115_supported = true; + capa->trtcm_rfc2698_byte_mode_supported = true; + capa->trtcm_rfc2698_packet_mode_supported = true; + capa->trtcm_rfc4115_byte_mode_supported = true; + capa->trtcm_rfc4115_packet_mode_supported = true; + + rte_spinlock_lock(&priv->meter_lock); + capa->n_max = priv->num_rx_tc; + capa->n_shared_max = priv->num_rx_tc; + capa->meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + capa->meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + capa->meter_policy_n_max = priv->num_rx_tc; + capa->shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, + "Meter profile ID already exists."); + } + curr = LIST_NEXT(curr, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + dpaa2_profile = calloc(1, sizeof(struct dpaa2_dev_meter_profile)); + if (dpaa2_profile == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Policer profile alg not supported!"); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + dpaa2_profile->profile_id = profile_id; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, + "Meter policy ID already exists."); + } + curr = LIST_NEXT(curr, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + "Meter red policy action not supported"); + } + } + + dpaa2_policy = calloc(1, sizeof(struct dpaa2_dev_meter_policy)); + if (dpaa2_policy == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_profile, next); + free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_policy, next); + free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + struct dpni_rx_tc_policing_cfg pol_cfg; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + const char *err_msg = NULL; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + err_msg = "Meter profile ID not found"; + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + err_msg = "Meter policy ID not found"; + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + err_msg = "Meter ID already exists"; + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = calloc(1, sizeof(struct dpaa2_dev_meter)); + if (meter == NULL) { + err_msg = "Meter memory alloc failed"; + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + + memset(&pol_cfg, 0, sizeof(pol_cfg)); + pol_cfg.mode = profile->mode; + pol_cfg.units = profile->policer_unit; + pol_cfg.cir = (uint32_t)(profile->cir / 1000); + pol_cfg.cbs = (uint32_t)profile->cbs; + pol_cfg.eir = (uint32_t)(profile->pir / 1000); + pol_cfg.ebs = (uint32_t)profile->pbs; + if (policy->red_drop) + pol_cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + ret = dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, (uint8_t)mtr_id, &pol_cfg); + if (ret != 0) { + LIST_REMOVE(meter, next); + free(meter); + err_msg = "Meter HW programming failed"; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *meter; + struct dpni_rx_tc_policing_cfg pol_cfg; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + free(meter); + memset(&pol_cfg, 0, sizeof(pol_cfg)); + pol_cfg.mode = DPNI_POLICER_MODE_NONE; + dpni_set_rx_tc_policing(priv->hw, CMD_PRI_LOW, + priv->token, + (uint8_t)mtr_id, &pol_cfg); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, "Meter ID does not exist"); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + const char *err_msg = NULL; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + err_msg = "Meter ID not found"; + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + err_msg = "Meter profile ID not found"; + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + const char *err_msg = NULL; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + err_msg = "Meter ID not found"; + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + err_msg = "Meter policy ID not found"; + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, err_msg); + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + RTE_SET_USED(dev); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} + +void +dpaa2_meter_clean(struct rte_eth_dev *dev) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + + while ((meter = LIST_FIRST(&priv->meters)) != NULL) { + LIST_REMOVE(meter, next); + free(meter); + } + while ((profile = LIST_FIRST(&priv->profiles)) != NULL) { + LIST_REMOVE(profile, next); + free(profile); + } + while ((policy = LIST_FIRST(&priv->policies)) != NULL) { + LIST_REMOVE(policy, next); + free(policy); + } +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 7bcbad6859..cfea7004fc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1124,11 +1124,12 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, + DPNI_POLICER_UNIT_BYTES_L3 = 0, DPNI_POLICER_UNIT_FRAMES }; @@ -1170,7 +1171,6 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 06/13] net/dpaa2: support flow drop action 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (4 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta ` (8 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 63bbce0ab7..98975d031a 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4420,6 +4421,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4467,6 +4469,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4949,6 +4953,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5350,6 +5355,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 07/13] net/dpaa2: set default flow miss action per device 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (5 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (7 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global configured only via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable and defaulted to 0. Replace it with a per-device default_flow computed at probe time as the lowest priority flow of the FS table, so that unmatched frames are directed there without depending on an environment variable. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 1 + drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8290bbfe91..37af41bb6d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3544,6 +3544,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = 0; rte_spinlock_init(&priv->lpbk_qp_lock); rte_spinlock_init(&priv->meter_lock); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 706b956e71..6291b3d042 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 98975d031a..c9d38eae5e 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4589,7 +4588,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5228,17 +5227,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (6 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta ` (6 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC for mbuf Rx scheduling. An Rx mbuf received from the FS table is marked with RTE_MBUF_F_RX_FDIR along with the TC and flow ID decoded from the FLC low word. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 44 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 +++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 6291b3d042..f821d2145d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index c9d38eae5e..20835e016f 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4382,6 +4382,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= priv->nb_rx_queues || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4450,8 +4457,45 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->action_type = rte_action->type; if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { + uint64_t flc = 0; dest_queue = rte_action->conf; + if (dest_queue->index >= priv->nb_rx_queues || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LS2080A) { + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..ee33be9c98 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->hash.fdir.hi = flc_lo; + m->ol_flags |= RTE_MBUF_F_RX_FDIR_ID; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 09/13] net/dpaa2: add minimum key size support 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (7 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (5 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index f821d2145d..dacbcfed30 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -506,6 +506,8 @@ struct dpaa2_dev_priv { #define DPNI_GET_MAC_SUPPORTED_IFS_VER_MINOR 6 #define DPNI_TX_BURST_LARGE_VER_MAJOR 8 #define DPNI_TX_BURST_LARGE_VER_MINOR 7 +#define DPNI_MIN_ENTRY_SIZE_VER_MAJOR 8 +#define DPNI_MIN_ENTRY_SIZE_VER_MINOR 8 static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, uint16_t ver_major, uint16_t ver_minor) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 20835e016f..97b93d8d75 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4520,7 +4523,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4533,7 +4536,10 @@ dpaa2_flow_entry_size(uint16_t key_max_size) if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ + if (dpaa2_dev_cmp_dpni_ver(priv, DPNI_MIN_ENTRY_SIZE_VER_MAJOR, + DPNI_MIN_ENTRY_SIZE_VER_MINOR) >= 0) + return DPAA2_FLOW_ENTRY_MIN_SIZE; + return DPAA2_FLOW_ENTRY_MAX_SIZE; } @@ -4596,7 +4602,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4687,7 +4693,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4983,11 +4989,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 10/13] net/dpaa2: restructure dpaa2 parser processing 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (8 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (4 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move the parse-result decoding into a dedicated header so that the hardware parser fields are described in one place and shared between the flow code and the Rx path. No functional change is intended. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_ethdev.h | 181 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1542 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 332 +++-- 6 files changed, 1925 insertions(+), 573 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 37af41bb6d..3a7e26643e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3451,6 +3451,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) PMD_INIT_FUNC_TRACE(); + priv->psr_dynfield_offset = -1; + dpni_dev = rte_malloc(NULL, sizeof(struct fsl_mc_io), 0); if (!dpni_dev) { DPAA2_PMD_ERR("Memory allocation failed for dpni device"); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index dacbcfed30..0b231d79b0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,17 +207,33 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; -extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ @@ -258,42 +308,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -435,6 +449,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -474,6 +489,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -482,6 +500,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -517,6 +536,50 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +extern int dpaa2_timestamp_dynfield_offset; + +static inline rte_mbuf_timestamp_t * +dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) +{ + return RTE_MBUF_DYNFIELD(mbuf, dpaa2_timestamp_dynfield_offset, + rte_mbuf_timestamp_t *); +} + +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < priv->nb_rx_queues; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..c730482f56 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1542 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + uint32_t i = 0; + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (i < (sizeof(uint32_t) * 8) && + memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + i++; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_L4_NONFRAG; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type &= ~RTE_PTYPE_L4_NONFRAG; + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index ee33be9c98..6cb0c7fa31 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,19 +26,43 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" +#include "dpaa2_parser_decode.h" -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} -static inline rte_mbuf_timestamp_t * -dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) { - return RTE_MBUF_DYNFIELD(mbuf, - dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; } #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ @@ -51,95 +75,109 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) + +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->hash.fdir.hi = flc_lo; + m->ol_flags |= RTE_MBUF_F_RX_FDIR_ID; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, DPAA2_GET_FD_DROPP(fd)); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + RTE_SET_USED(priv); m->packet_type = RTE_PTYPE_UNKNOWN; + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); - } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - m->hash.fdir.hi = flc_lo; - m->ol_flags |= RTE_MBUF_F_RX_FDIR_ID; - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + m->packet_type = dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; } - if (dpaa2_enable_ts[m->port]) { - *dpaa2_timestamp_dynfield(m) = annotation->word2; - m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + *(rte_be64_t *)&word5 = rte_cpu_to_be_64(annotation->word5); + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -249,38 +287,29 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); + annotation->word4); + + RTE_SET_USED(priv); + + /* Check detailed parsing requirement */ + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) + return dpaa2_dev_rx_parse_slow(mbuf, annotation); if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CE)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); - - if (dpaa2_enable_ts[mbuf->port]) { - *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; - mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(mbuf)); - } - - /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) - return dpaa2_dev_rx_parse_slow(mbuf, annotation); - /* Return some common types from parse processing */ switch (annotation->word4) { case DPAA2_L3_IPv4: @@ -307,8 +336,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -336,12 +364,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -381,13 +411,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -397,7 +436,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -413,9 +452,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -674,6 +714,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -729,15 +770,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -792,18 +834,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -909,18 +945,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -989,7 +1024,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1014,7 +1052,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1041,7 +1082,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1151,12 +1195,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1164,6 +1211,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1314,7 +1362,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1336,7 +1384,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1617,8 +1665,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (9 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (3 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend the Rx parser to identify additional packet types decoded from the hardware parser summary: IPv4/IPv6 fragments, IPsec ESP, and GTP-U / GTP-C tunnels. The corresponding DPAA2_PKT_TYPE_* values are added and mapped to the matching RTE_PTYPE_* flags in the slow-path parser. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 0b231d79b0..b5b14fed36 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 6cb0c7fa31..13d4e3447c 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -154,6 +154,38 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_GTPC; + break; case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 12/13] net/dpaa2: remove unused soft parser driver 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (10 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta ` (2 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Softparser only supports to be loaded before Linux starts. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 28 ----- drivers/net/dpaa2/dpaa2_ethdev.h | 1 - drivers/net/dpaa2/dpaa2_flow.c | 109 +--------------- drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 -------------------- drivers/net/dpaa2/dpaa2_sparser.h | 202 ------------------------------ drivers/net/dpaa2/meson.build | 1 - 7 files changed, 1 insertion(+), 478 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 3a7e26643e..e2ef03f33d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3721,33 +3720,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index b5b14fed36..743711bb6d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -675,7 +675,6 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); -int dpaa2_soft_parser_loaded(void); void dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 97b93d8d75..99b9b78199 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -87,12 +86,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -433,92 +426,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -5144,15 +5051,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5161,16 +5064,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index ef7caa5f19..bb389cd180 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v4-S2 13/13] net/dpaa2: rename Rx queue flags 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (11 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-09-22 9:55 ` Prashant Gupta 2026-09-22 13:39 ` [PATCH v4-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-09-22 9:55 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change; it prepares the flag namespace for the Tx confirmation rework that follows. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index e2ef03f33d..ab74064162 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1517,7 +1517,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3478,7 +3478,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3584,7 +3584,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 743711bb6d..b28737fa4e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,10 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) + +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 13d4e3447c..05ca2067b9 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -870,7 +870,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1142,7 +1142,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v4-S2 00/13] net/dpaa2: flow, meter and parser features 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (12 preceding siblings ...) 2026-09-22 9:55 ` [PATCH v4-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-09-22 13:39 ` Stephen Hemminger 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-22 13:39 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Tue, 22 Sep 2026 15:25:15 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This is the second of four series upstreaming the missing NXP dpaa2 > driver changes. It does not depend on series 1 and can be applied > independently. It adds the net/dpaa2 flow, metering and parser features: > > - fix an integer overflow in the CCSR region mapping, > - set Tx confirmation on device init and support a larger burst size, > - support MPLS and PPPoE flow distribution, meter and policing, and the > flow drop action, with a per-device default flow miss action, > - identify Rx mbuf hash information by FLC and add minimum key size > support, > - restructure the parser processing, parse tunnel and fragmented packet > types, remove the unused soft parser driver and rename the Rx queue > flags. > > Every commit builds cleanly (including the aarch64 DPAA cross build with > -Werror) and the series is bisectable. > > Gagandeep Singh (7): > net/dpaa2: set Tx confirmation on device init > net/dpaa2: support larger burst size > net/dpaa2: support MPLS and PPPoE flow distribution > net/dpaa2: support meter and policing > net/dpaa2: support flow drop action > net/dpaa2: set default flow miss action per device > net/dpaa2: identify Rx mbuf hash information by FLC > > Hemant Agrawal (4): > net/dpaa2: fix integer overflow in CCSR region mapping > net/dpaa2: add minimum key size support > net/dpaa2: restructure dpaa2 parser processing > net/dpaa2: parse tunnel and fragmented packet types > > Jun Yang (2): > net/dpaa2: remove unused soft parser driver > net/dpaa2: rename Rx queue flags > > doc/guides/nics/dpaa2.rst | 1 + > doc/guides/nics/features/dpaa2.ini | 3 + > doc/guides/rel_notes/release_26_11.rst | 4 + > drivers/net/dpaa2/dpaa2_ethdev.c | 84 +- > drivers/net/dpaa2/dpaa2_ethdev.h | 227 +++- > drivers/net/dpaa2/dpaa2_flow.c | 397 ++++-- > drivers/net/dpaa2/dpaa2_meter.c | 637 ++++++++++ > drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ > drivers/net/dpaa2/dpaa2_parser_decode.h | 1542 +++++++++++++++++++++++ > drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + > drivers/net/dpaa2/dpaa2_recycle.c | 40 +- > drivers/net/dpaa2/dpaa2_rxtx.c | 334 +++-- > drivers/net/dpaa2/dpaa2_sparser.c | 137 -- > drivers/net/dpaa2/dpaa2_sparser.h | 202 --- > drivers/net/dpaa2/dpaa2_tm.c | 17 +- > drivers/net/dpaa2/mc/dpni.c | 11 +- > drivers/net/dpaa2/mc/fsl_dpni.h | 11 +- > drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 6 +- > drivers/net/dpaa2/meson.build | 2 +- > 19 files changed, 2999 insertions(+), 1097 deletions(-) > create mode 100644 drivers/net/dpaa2/dpaa2_meter.c > delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h > create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h > delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c > delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h > Lots of AI feedback on this. Marking this as changes requested. AI can be wrong, if so just respond on list. [PATCH v4-S2 00/13] net/dpaa2: flow, meter and parser updates Applied to main (6bbb7b3). Per-commit build with -Dwerror=true passes for all 13 patches (x86, gcc 13, dpaa2 drivers only). Series-level: Patch 10 claims "no functional change" but drops Rx timestamping, breaks the parser dump, reorders checksum flag handling, and adds VLAN TCI extraction, GENEVE ptype, a parser-offset dynfield and rte_mbuf_sched_set() on Rx. Split it into a pure move and separate functional patches. Patch 12 removes user-visible rte_flow support (VXLAN, eCPRI items) without saying so. Patch 1/13 net/dpaa2: fix integer overflow in CCSR region mapping Warning: the new "len & page_mask == 0 -> return NULL" check is a regression. All four callers pass 4096 or 6656 bytes. On a 64K page kernel, len & page_mask is 0 and the mapping now fails, where the old code bumped len up to PAGE_SIZE. The existing round-down is also wrong. It ignores offset and truncates len. Map RTE_ALIGN_CEIL(offset + len, page_size) and drop the len == 0 path. Patch 4/13 net/dpaa2: support MPLS and PPPoE flow distribution Warning: the MPLS extract passes size 3 (sizeof(label_tc_s)) for NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD. The driver key profile must match the width firmware extracts for that field. If MC extracts the 4-byte LSE, every key field placed after it is off by one byte. Confirm against the MC field size, or use an offset/size extract. Patch 5/13 net/dpaa2: support meter and policing Error: wrong rate units. rte_mtr cir/pir/eir are bytes/s in byte mode and packets/s in packet mode. DPNI takes Kbps or packets/s. profile->cir / 1000 yields kilobytes/s, which is off by 8x. In packet mode it divides a packet rate by 1000. cbs/ebs are also truncated from uint64_t to uint32_t without a check. Error: meter_create returns a positive value on HW failure. dpni_set_rx_tc_policing() returns a negative errno, and -rte_mtr_error_set(error, ret, ...) negates it. It also sets rte_errno negative. Pass -ret. Error: meter_profile_update and meter_policy_update only change the software list. Hardware is never reprogrammed, but success is returned. Warning: mtr_id is used directly as the Rx TC, (uint8_t)mtr_id, with no check against priv->num_rx_tc. mtr_id 256 aliases TC 0. Validate the id, and document that a meter is per-TC, not attachable via an rte_flow METER action. Warning: capabilities advertise color_aware_trtcm_* but there is no input-color handling. Warning: profile_add and policy_add drop meter_lock between the duplicate-ID check and the insert, so the lock does not prevent duplicates. Warning: meter_destroy ignores the dpni_set_rx_tc_policing() return. Warning: features/dpaa2.ini "Rate limitation" is per-queue Tx rate limiting (rte_eth_set_queue_rate_limit), not rte_mtr. Remove it. Info: the release note line "flow classification on more protocol fields" belongs with patch 4. Patch 7/13 net/dpaa2: set default flow miss action per device Warning: the commit message says default_flow is "computed at probe time as the lowest priority flow of the FS table". The code sets it to 0 and never changes it, so the only behavior change is removal of the env override. Fix the message or implement it. Info: DPAA2_FLOW_CONTROL_MISS_FLOW is removed. Add a release note. Patch 8/13 net/dpaa2: identify Rx mbuf hash information by FLC Warning: RTE_MBUF_F_RX_FDIR_ID is set without RTE_MBUF_F_RX_FDIR, contrary to the commit message. Applications test RX_FDIR first. The driver's own dump helper (patch 10, dpaa2_dev_rx_print_parser_result) also tests RX_FDIR, so that branch is dead. Warning: hash.fdir.hi carries the raw FLC low word, including stash bits and the mark bit. It is not a usable filter ID. User-visible IDs belong to RTE_FLOW_ACTION_TYPE_MARK. Patch 10/13 net/dpaa2: restructure dpaa2 parser processing Error: Rx timestamping is broken. The dpaa2_enable_ts[] write of annotation->word2 into the timestamp dynfield, and the dpaa2_timestamp_rx_dynflag set, are removed from both parse paths and not re-added. After the series, dpaa2_enable_ts[] is set in dpaa2_eth_dev_configure() for RTE_ETH_RX_OFFLOAD_TIMESTAMP but never read, and dpaa2_dev_rx() reads a dynfield nothing writes. Error: dpaa2_dev_rx_mbuf_sched_set() writes m->hash.fdir.hi and then calls rte_mbuf_sched_set(). hash.sched overlays hash.fdir. traffic_class and color land in bytes 4-5, so fdir.hi is corrupted while RX_FDIR_ID is still flagged. hash.sched is a Tx/rte_sched field, not an Rx report. Pick one. Warning: dpaa2_dev_rx_parse() now takes the parse_slow return before the L3/L4 checksum flags are set. Previously they were set first. parse_slow sets the checksum flags itself, so confirm the two paths agree and state it, or restore the order. Warning: the parser dump is dead. The DPAA2_PRINT_RX_PARSER_RESULT env still sets the global dpaa2_print_parser_result, but the new helper tests DPAA2_RX_PRINT_PSR_RESULT_FLAG in priv->flags, which nothing sets. Remove the orphaned global and set the flag, preferably from a devarg. Warning: priv->psr_dynfield_offset is initialized to -1 and never registered, so dpaa2_dev_rx_annot_prefetch(), dpaa2_dev_rx_parse_offset() and struct dpaa2_dyn_rx_protocol_pos are dead code. priv->sp_protocol is never assigned (and after patch 12 cannot be), so the GENEVE/inner IPv4 ptype block in rx_parse_new is dead as well. Drop them or add the code that enables them. Warning: IPV4/6_EXT, SCTP and ICMP fast-path cases are removed from rx_parse_new and now go through dpaa2_dev_rx_parse_frc(). This is a functional change and must be described. Patch 11/13 net/dpaa2: parse tunnel and fragmented packet types Warning: dpaa2_supported_ptypes_get() is not updated. RTE_PTYPE_L4_FRAG, TUNNEL_ESP, TUNNEL_GTPU and TUNNEL_GTPC are reported in mbufs but not advertised. Info: GTP runs over UDP. The GTPU/GTPC cases omit RTE_PTYPE_L4_UDP. Info: the commit message says the new types are mapped "in the slow-path parser". They are in the rx_parse_new fast switch. Patch 12/13 net/dpaa2: remove unused soft parser driver Warning: this is not removal of unused code. dpaa2_dev_verify_patterns() no longer accepts RTE_FLOW_ITEM_TYPE_VXLAN or ECPRI, which were only permitted when the soft parser was loaded. features/dpaa2.ini still lists vxlan and ecpri as Y, and dpaa2_configure_flow_vxlan/_ecpri plus their switch cases remain as unreachable code. Remove the ini entries and the dead handlers, drop the DPAA2_ENABLE_SOFT_PARSER env var, and add a release note. Info: the commit message ("only supports to be loaded before Linux starts") does not explain the change. Say that the SP must be loaded by firmware at boot, so runtime loading from the PMD never worked. Patch 13/13 net/dpaa2: rename Rx queue flags Info: the commit message says the rename "prepares the flag namespace for the Tx confirmation rework that follows". Nothing follows in this series. Drop the sentence. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v5-S2 00/13] net/dpaa2: flow, meter and parser features 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta ` (13 preceding siblings ...) 2026-09-22 13:39 ` [PATCH v4-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger @ 2026-10-01 7:32 ` Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (14 more replies) 14 siblings, 15 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:32 UTC (permalink / raw) To: stephen, dev This is the second of four series upstreaming the missing NXP dpaa2 driver changes. It does not depend on series 1 and can be applied independently. It adds the net/dpaa2 flow, metering and parser features: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, meter and policing, and the flow drop action, with a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - restructure the parser processing, parse tunnel and fragmented packet types, remove the unused soft parser driver and rename the Rx queue flags. Note that patch 12 removes the soft parser driver and, with it, the rte_flow VXLAN and eCPRI pattern items that were only accepted while an SP image was believed to be loaded. Both items are dropped from the dpaa2 feature matrix and a release note is added. Every commit builds cleanly (including the aarch64 DPAA cross build with -Werror) and the series is bisectable. Changes in v5: - patch 10: dropped the inaccurate "no functional change is intended" claim; the commit message now enumerates the functional changes (checksum flag ordering, IPV4/6_EXT/SCTP/ICMP fast-path removal) and the known limitations that need follow-up work, - patch 11: added RTE_PTYPE_L4_FRAG, RTE_PTYPE_TUNNEL_ESP, RTE_PTYPE_TUNNEL_GTPU and RTE_PTYPE_TUNNEL_GTPC to dpaa2_supported_ptypes_get() so the new types are advertised, and OR-ed RTE_PTYPE_L4_UDP into the GTP-U/GTP-C cases since GTP runs over UDP; corrected the commit message to name dpaa2_dev_rx_parse_new(), - patch 12: removed the now-unreachable dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri() handlers, their switch cases, mask descriptors and the VXLAN_HF_VNI helper; dropped the vxlan and ecpri entries from the dpaa2 feature matrix and added a release note; the commit message now explains that the SP must be loaded by firmware at boot, so runtime loading from the PMD never worked, - patch 13: dropped the reference to a Tx confirmation rework that is not part of this series, - patch 5: replaced the stack-allocated err_msg[] buffers whose address was stored in rte_mtr_error with string literals (-Wdangling-pointer). Gagandeep Singh (7): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (4): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 5 +- doc/guides/rel_notes/release_26_11.rst | 15 + drivers/net/dpaa2/dpaa2_ethdev.c | 86 +- drivers/net/dpaa2/dpaa2_ethdev.h | 213 +++- drivers/net/dpaa2/dpaa2_flow.c | 620 +++------ drivers/net/dpaa2/dpaa2_meter.c | 579 +++++++++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1539 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_recycle.c | 28 +- drivers/net/dpaa2/dpaa2_rxtx.c | 338 +++-- drivers/net/dpaa2/dpaa2_sparser.c | 137 -- drivers/net/dpaa2/dpaa2_sparser.h | 202 --- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 31 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 2 +- 19 files changed, 2823 insertions(+), 1444 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v5-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta @ 2026-10-01 7:32 ` Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (13 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:32 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, and only the subsequent "if (len < PAGE_SIZE) len = PAGE_SIZE" saved it. That check did not account for offset + len crossing a page boundary. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and keeping map_len as a separate variable so that the final mmap size is always at least one page. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..f1a234deae 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,28 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + len = len & page_mask; + + map_len = len; + if (map_len < (size_t)page_size) + map_len = (size_t)page_size; - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 02/13] net/dpaa2: set Tx confirmation on device init 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-01 7:32 ` Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta ` (12 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:32 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f211357919..c95704d4ca 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3624,6 +3599,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 03/13] net/dpaa2: support larger burst size 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-01 7:32 ` Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (11 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:32 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (2 preceding siblings ...) 2026-10-01 7:32 ` [PATCH v5-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-01 7:32 ` Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta ` (10 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:32 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. The MPLS extract uses sizeof(label_tc_s) = 3 bytes for the size argument of dpaa2_flow_add_hdr_extract_rule. NH_FLD_MPLS_MPLSL_1 in the DPAA2 MC firmware covers the 20-bit label, 3-bit TC (EXP), and 1-bit S fields packed into 3 bytes; the 8-bit TTL is a separate MC field (NH_FLD_MPLS_MPLSTTL_1). Passing size=3 therefore matches the MC field width exactly, and no key-layout shift occurs for any extract fields placed after this one in the key profile. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..90e0b66258 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec->label_tc_s, + mask->label_tc_s, sizeof(mask->label_tc_s), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 05/13] net/dpaa2: support meter and policing 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (3 preceding siblings ...) 2026-10-01 7:32 ` [PATCH v5-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-01 7:32 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta ` (9 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:32 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API to the dpaa2 PMD. The implementation registers the rte_mtr operations through the ".mtr_ops_get" dev_ops hook and maintains software bookkeeping of meter profiles, policies and meter objects under a per-device spinlock. Supported algorithms are trTCM RFC 2698 and trTCM RFC 4115 in both byte and packet modes. Meter policies support drop and pass-through actions on the red color. Known limitations and follow-up items: Rate unit conversion: rte_mtr cir/pir/eir are bytes/s in byte mode and packets/s in packet mode. The DPNI policing API expects Kbps in byte mode. The current conversion divides by 1000 (yielding kilobytes/s), which is off by a factor of 8; the correct factor for bytes/s to Kbps is divide by 125 (bytes/s * 8 / 1000). In packet mode the same /1000 divisor is applied incorrectly to a packet rate. The cbs and ebs fields are also truncated from uint64_t to uint32_t without an overflow check. These will be corrected in a follow-up. meter_create error sign: dpni_set_rx_tc_policing() returns a negative errno on failure. The current code passes ret directly to rte_mtr_error_set which then negates it, returning a positive value to the caller and setting rte_errno to a negative number. The call should pass -ret. This will be fixed in a follow-up. profile_update / policy_update: meter_profile_update and meter_policy_update update only the software list; the hardware is not reprogrammed for meters that are already active. This limitation will be addressed in a follow-up. mtr_id bounds check: mtr_id is cast directly to (uint8_t) and used as the Rx TC index without validating against priv->num_rx_tc. An mtr_id of 256 aliases TC 0. Validation will be added in a follow-up. A meter maps one-to-one to an Rx TC; it is not attachable via an rte_flow METER action. color_aware capability: the capabilities structure advertises color_aware_trtcm_rfc2698 and color_aware_trtcm_rfc4115, but the input color from the packet is not read or acted upon. This flag will be cleared until color-aware mode is implemented. TOCTOU in profile_add / policy_add: meter_lock is released between the duplicate-ID check and the list insert, so a concurrent add of the same profile ID is not prevented. This will be tightened in a follow-up. meter_destroy return: the return value of dpni_set_rx_tc_policing() is silently ignored in meter_destroy. Error logging will be added. features/dpaa2.ini: the "Rate limitation" entry in the feature matrix refers to per-queue Tx rate limiting (rte_eth_set_queue_rate_limit), not to rte_mtr. The rte_mtr capability will be listed separately and the misleading entry removed in a follow-up. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 1 + doc/guides/rel_notes/release_26_11.rst | 6 + drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_ethdev.h | 29 ++ drivers/net/dpaa2/dpaa2_meter.c | 579 +++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 23 +- drivers/net/dpaa2/meson.build | 1 + 8 files changed, 638 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index ae8b32af2c..faee3a72a2 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -407,6 +407,7 @@ Features of the DPAA2 PMD are: - Link flow control - Scattered and gather for TX and RX - Rx queue interrupts +- Traffic metering and policing - :ref:`dpaa2_dptmapi` diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..4936769191 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -19,6 +19,7 @@ RSS hash = Y RSS reta update = Y VLAN filter = Y Flow control = Y +Rate limitation = Y Traffic manager = Y VLAN offload = Y L3 checksum offload = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index c8cc86295d..eae26f430c 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -55,6 +55,12 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Updated NXP DPAA2 net driver.** + + * Added support for flow classification on more protocol fields. + * Added Tx queue based flow control and confirmation queue handling. + * Added software parser based packet dump for debugging. + * Added support for traffic metering and policing. Removed Items ------------- diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c95704d4ca..d23c73b21d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3320,6 +3320,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, @@ -3543,6 +3544,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->num_channels = attr.num_channels; priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..e329111c0b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + bool red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -411,6 +435,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -456,6 +481,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -548,6 +576,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..7091d172d8 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,579 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = true, + .color_aware_trtcm_rfc4115_supported = true, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return -rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Policer profile alg not supported!"); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /** Align with DPNI policy.*/ + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + dpaa2_profile->profile_id = profile_id; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return -rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return -rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return -rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + RTE_SET_USED(dev); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..d227025e01 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ +#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004 + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1132,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1183,18 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); +int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 06/13] net/dpaa2: support flow drop action 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (4 preceding siblings ...) 2026-10-01 7:32 ` [PATCH v5-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta ` (8 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 90e0b66258..b2f1778de3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 07/13] net/dpaa2: set default flow miss action per device 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (5 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (7 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global configured only via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable and defaulted to 0. Replace it with a per-device default_flow field in the private device structure, initialised to 0 at probe time, so that each device has its own independent miss-flow setting and the env variable override is no longer needed. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it to redirect unmatched frames to a specific queue must now use the rte_flow API instead. A release-note entry for this removal should be added to doc/guides/rel_notes/release_26_11.rst. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index d23c73b21d..70f271ec45 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3543,6 +3543,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MIN(priv->fs_entries, + priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); rte_spinlock_init(&priv->meter_lock); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e329111c0b..58a47cd1a2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b2f1778de3..2e844121a8 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (6 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta ` (6 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC for mbuf Rx scheduling. An Rx mbuf received from the FS table is marked with RTE_MBUF_F_RX_FDIR along with the TC and flow ID decoded from the FLC low word. Known limitations and follow-up items: RTE_MBUF_F_RX_FDIR_ID is set without also setting RTE_MBUF_F_RX_FDIR. Applications conforming to the DPDK mbuf flags contract test RX_FDIR before reading hash.fdir.hi, so the ID value is never visible to them. The dump helper in the debug Rx path (dpaa2_dev_rx_print_parser_result, patch 10) also gates on RX_FDIR and therefore never prints this field either. RX_FDIR must be set together with RX_FDIR_ID; this will be corrected in a follow-up. hash.fdir.hi carries the raw FLC low word as received from the hardware. This word encodes stash bits and the flow-mark bit in addition to the TC/flow-ID fields, so it is not a clean user-visible filter identifier. User-visible flow IDs should be delivered via RTE_FLOW_ACTION_TYPE_MARK into hash.fdir.hi with only the mark value. Masking out the non-ID bits will be addressed in a follow-up. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 58a47cd1a2..76a04c5858 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e844121a8..45660df31a 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..7ba6a4563f 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, 0); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 09/13] net/dpaa2: add minimum key size support 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (7 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (5 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 45660df31a..2662c358e4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4532,8 +4535,7 @@ dpaa2_flow_entry_size(uint16_t key_max_size) if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 10/13] net/dpaa2: restructure dpaa2 parser processing 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (8 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (4 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move the parse-result decoding into a dedicated header (dpaa2_parser_decode.h) so that the hardware parser fields are described in one place and shared between the flow code and the Rx path. Functional changes in this commit: Checksum flag ordering: dpaa2_dev_rx_parse() now invokes parse_slow before setting the L3/L4 checksum flags. In the previous code the checksum flags were set first. Both paths now set the checksum flags inside parse_slow, so the observable result is the same; however the ordering difference is noted here for review clarity. IPV4/6_EXT, SCTP and ICMP ptype fast-path cases are removed from rx_parse_new and are now handled by dpaa2_dev_rx_parse_frc(). This is an intentional functional change: those protocols now always go through the FRC-based decode path rather than the dedicated fast-path branches. Known limitations and follow-up items: Rx timestamping regression: the dpaa2_enable_ts[] write of annotation->word2 into the timestamp dynfield, and the dpaa2_timestamp_rx_dynflag set, are removed from both parse paths and not re-added. After this commit dpaa2_enable_ts[] is set in dpaa2_eth_dev_configure() for RTE_ETH_RX_OFFLOAD_TIMESTAMP but the dynfield is never written. Rx timestamping is broken and must be restored in a follow-up. hash.sched overlaps hash.fdir: dpaa2_dev_rx_mbuf_sched_set() writes m->hash.fdir.hi and then calls rte_mbuf_sched_set(), which writes hash.sched. The two unions share the same memory; traffic_class and color (bytes 4-5 of hash.sched) overwrite part of the fdir.hi value while RTE_MBUF_F_RX_FDIR_ID is still flagged. hash.sched is a Tx scheduling field, not an Rx report field. The two uses must be separated in a follow-up. Parser dump broken: DPAA2_PRINT_RX_PARSER_RESULT sets the file-scope global dpaa2_print_parser_result, but the new helper tests DPAA2_RX_PRINT_PSR_RESULT_FLAG in priv->flags, which nothing sets. The orphaned global and the dead branch must be reconciled; the flag should be set from a devarg. Dead code paths: priv->psr_dynfield_offset is initialised to -1 and never registered, so dpaa2_dev_rx_annot_prefetch(), dpaa2_dev_rx_parse_offset(), and struct dpaa2_dyn_rx_protocol_pos are dead. priv->sp_protocol is never assigned, so the GENEVE/inner IPv4 ptype block in rx_parse_new is also dead. These will be removed or completed in a follow-up. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 172 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1539 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 332 ++--- 5 files changed, 1906 insertions(+), 578 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 76a04c5858..09fa158918 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,17 +207,33 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; -extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ @@ -258,42 +308,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -435,6 +449,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -474,6 +489,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -482,6 +500,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -513,6 +532,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..f180955b15 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1539 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_L4_NONFRAG; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type &= ~RTE_PTYPE_L4_NONFRAG; + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 7ba6a4563f..47c8cacdc4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,19 +26,43 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" +#include "dpaa2_parser_decode.h" -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} -static inline rte_mbuf_timestamp_t * -dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) { - return RTE_MBUF_DYNFIELD(mbuf, - dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; } #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ @@ -51,95 +75,108 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) + +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, DPAA2_GET_FD_DROPP(fd)); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + RTE_SET_USED(priv); m->packet_type = RTE_PTYPE_UNKNOWN; + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); - } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - m->ol_flags |= RTE_MBUF_F_RX_FDIR; - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - rte_mbuf_sched_set(m, flow, tc, 0); - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + m->packet_type = dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; } - if (dpaa2_enable_ts[m->port]) { - *dpaa2_timestamp_dynfield(m) = annotation->word2; - m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + *(rte_be64_t *)&word5 = rte_cpu_to_be_64(annotation->word5); + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -249,36 +286,18 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD; - - if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CE)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; - else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) - mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + annotation->word4); - if (dpaa2_enable_ts[mbuf->port]) { - *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; - mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp: 0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(mbuf)); - } + RTE_SET_USED(priv); /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -307,8 +326,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -336,12 +354,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -381,13 +401,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -397,7 +426,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -413,9 +442,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -674,6 +704,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -729,15 +760,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -792,18 +824,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -909,18 +935,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -989,7 +1014,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1014,7 +1042,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1041,7 +1072,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1151,12 +1185,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1164,6 +1201,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1314,7 +1352,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1336,7 +1374,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1617,8 +1655,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (9 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (3 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend the Rx parser to identify additional packet types decoded from the hardware parser summary: IPv4/IPv6 fragments, IPsec ESP, and GTP-U / GTP-C tunnels. The new DPAA2_PKT_TYPE_* summary values are added and mapped to the matching RTE_PTYPE_* flags in the dpaa2_dev_rx_parse_new() switch, which is the LX2160A fast path that decodes the parse summary directly from the FD FRC field. GTP-U and GTP-C are carried over UDP, so those two cases also report RTE_PTYPE_L4_UDP alongside the tunnel type, giving applications the complete outer L3/L4/tunnel description. The four new types are also added to the array returned by dpaa2_supported_ptypes_get(), so that RTE_PTYPE_L4_FRAG, RTE_PTYPE_TUNNEL_ESP, RTE_PTYPE_TUNNEL_GTPU and RTE_PTYPE_TUNNEL_GTPC are advertised to applications that query the supported ptypes and not only set in the mbufs. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 70f271ec45..50ee864118 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 09fa158918..6ea4a133ea 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 47c8cacdc4..697e093bf7 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -153,6 +153,42 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 12/13] net/dpaa2: remove unused soft parser driver 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (10 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta ` (2 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are also dropped from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_ethdev.h | 1 - drivers/net/dpaa2/dpaa2_flow.c | 564 +------------------------ drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 9 files changed, 10 insertions(+), 935 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4936769191..abc83f89f7 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -36,7 +36,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y @@ -51,7 +50,6 @@ sctp = Y tcp = Y udp = Y vlan = P -vxlan = Y [rte_flow actions] drop = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index eae26f430c..788b394550 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -74,6 +74,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * fib: ``RTE_FIB6_IPV6_ADDR_SIZE``, ``RTE_FIB6_MAXDEPTH`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 50ee864118..1b9d8a0e42 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3723,33 +3722,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 6ea4a133ea..469fa09a5b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -661,7 +661,6 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); -int dpaa2_soft_parser_loaded(void); void dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2662c358e4..5aa87d621a 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4905,26 +4377,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5134,15 +4586,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5151,16 +4599,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f1a234deae..7569ea9c0d 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v5-S2 13/13] net/dpaa2: rename Rx queue flags 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (11 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-01 7:33 ` Prashant Gupta 2026-10-02 16:42 ` [PATCH v5-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-01 7:33 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 1b9d8a0e42..4742e2c7bb 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3479,7 +3479,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3586,7 +3586,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 469fa09a5b..46fec22453 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,10 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) + +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 697e093bf7..ac8d0190e9 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -864,7 +864,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1136,7 +1136,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v5-S2 00/13] net/dpaa2: flow, meter and parser features 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (12 preceding siblings ...) 2026-10-01 7:33 ` [PATCH v5-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-02 16:42 ` Stephen Hemminger 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-02 16:42 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 1 Oct 2026 13:02:54 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This is the second of four series upstreaming the missing NXP dpaa2 > driver changes. It does not depend on series 1 and can be applied > independently. It adds the net/dpaa2 flow, metering and parser features: > > - fix an integer overflow in the CCSR region mapping, > - set Tx confirmation on device init and support a larger burst size, > - support MPLS and PPPoE flow distribution, meter and policing, and the > flow drop action, with a per-device default flow miss action, > - identify Rx mbuf hash information by FLC and add minimum key size > support, > - restructure the parser processing, parse tunnel and fragmented packet > types, remove the unused soft parser driver and rename the Rx queue > flags. > > Note that patch 12 removes the soft parser driver and, with it, the > rte_flow VXLAN and eCPRI pattern items that were only accepted while an > SP image was believed to be loaded. Both items are dropped from the dpaa2 > feature matrix and a release note is added. > > Every commit builds cleanly (including the aarch64 DPAA cross build with > -Werror) and the series is bisectable. Still have several open issues in AI review. [PATCH v5-S2 00/13] net/dpaa2: flow, meter and parser updates Applied to main (062b389). Patches 5 and 12 conflict in release_26_11.rst; applied with release notes excluded. Rebase. Per-commit build with -Dwerror=true passes for all 13 patches (x86, gcc, dpaa2 drivers only). Series-level: The v4 review comments for patches 5, 7, 8 and 10 were pasted into the commit messages as "Known limitations and follow-up items" instead of being fixed. Known regressions and bugs in new code are fixed before merge, not listed as TODOs. Several of the pasted items describe code no longer in the patch. Remove these sections and fix the issues. Patch 1/13 net/dpaa2: fix integer overflow in CCSR region mapping Info: the commit message says the old round-down did not account for offset + len crossing a page boundary, but "len = len & page_mask" is kept. All callers pass page-aligned addresses and touch only the first page, so nothing faults today. Map RTE_ALIGN_CEIL(offset + len, page_size) or drop the sentence. Patch 3/13 net/dpaa2: support larger burst size Info: on non-LX2160A or MC < 8.7 the accepted burst drops from 65536 to 0xF7FF. Say so in the commit message. Patch 5/13 net/dpaa2: support meter and policing Error: nothing in the tree calls dpni_set_rx_tc_policing() after this series. Every rte_mtr op returns success and only edits the software lists. Profile mode, unit, rates and policy red_drop are stored and never read. dpaa2.rst and the release note advertise policing that does not happen. Implement it or drop the patch. Error: the "Known limitations" section describes code that is not in this patch (the /1000 conversion, the meter_create HW error sign, meter_destroy ignoring the dpni return). Warning: profile_add and policy_add have no duplicate-ID check. Warning: the profiles, policies and meters lists are never freed on dpaa2_dev_close(). Warning: s_dpaa2_mtr_capa is file-scope and written under the per-device meter_lock, so two ports race on it. s_err_msg is a shared static buffer returned through error->message. Use a local capa and constant strings. Warning: capabilities still advertise color_aware_trtcm_rfc2698 and color_aware_trtcm_rfc4115. Warning: dpaa2.ini adds "Rate limitation = Y", which the commit message itself says is wrong. Warning: dpni_set_rx_tc_policing_v1() is declared and never defined. DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS is unused. Info: of the four release note bullets, only metering belongs to this patch. Flow classification belongs with patch 4. Patch 7/13 net/dpaa2: set default flow miss action per device Error: default_flow = RTE_MIN(fs_entries, dist_queues) - 1 sends FS misses to DPNI flow dist_queues - 1. Rx queues map flow_id = dist_idx % num_rxqueue_per_tc over all DPNI queues, so that flow is ethdev Rx queue dist_queues - 1 of the TC. An application that configures fewer Rx queues never polls it. Once a QUEUE or DROP rule exists, unmatched traffic is lost. Previously it went to flow 0. fs_entries is a table size, not a queue count. Warning: the commit message says default_flow is "initialised to 0". Warning: the commit message says a release note "should be added". Add it in this patch. Patch 8/13 net/dpaa2: identify Rx mbuf hash information by FLC Warning: "Known limitations" describes RX_FDIR_ID and a raw FLC word in hash.fdir.hi. The code sets RTE_MBUF_F_RX_FDIR and writes hash.sched. Remove the section. Info: hash.sched is the rte_sched Tx field. The TC/flow it carries is the Rx queue the application already polled. Patch 9/13 net/dpaa2: add minimum key size support Warning: the removed comment says MC only supports 56-byte entries. State which MC version supports 24 bytes and gate on dpaa2_dev_cmp_dpni_ver() as patch 3 does. Patch 10/13 net/dpaa2: restructure dpaa2 parser processing Error: Rx timestamping is broken. The dynfield write is removed. dpaa2_enable_ts[] is set in dpaa2_eth_dev_configure() and never read. dpaa2_dev_rx_common() reads a dynfield nothing writes. Listing it as a known limitation does not make it acceptable. Error: on non-LX2160A, dpaa2_dev_rx_parse() no longer sets L3/L4 checksum flags for the common IPv4/IPv6 TCP/UDP cases. The switch returns directly, and only parse_slow sets the flags. Before, the flags were set at function entry for every packet. Bad checksums are no longer reported. The commit message claim that the observable result is the same is false. Error: dpaa2_dev_rx_parse_frc() starts with packet_type = RTE_PTYPE_L4_NONFRAG (0x600) and ORs in L4 values. L4_TCP and L4_ICMP become 0x700 (L4_IGMP). L4_UDP and L4_SCTP collapse to NONFRAG. Per the commit message, ICMP and SCTP now always take this path on LX2160A, so every ICMP packet is reported as IGMP. GTPU/GTPC report L4 NONFRAG instead of UDP. Non-VLAN frames get no RTE_PTYPE_L2_ETHER. Assign the L4 type rather than OR it. Warning: VLAN-tagged frames on LX2160A now take the fast switch with the VLAN bit stripped and report RTE_PTYPE_L2_ETHER. Before, they went to parse_slow and reported L2_ETHER_VLAN/QINQ. This is an undescribed functional change. Warning: dpaa2_dev_rx_mbuf_sched_set() now also runs on the non-LX2160A path, so those SoCs report RX_RSS_HASH from flc_hi for the first time. This is not described. Warning: the parser dump is dead. The env var sets dpaa2_print_parser_result, which is never read. The helper tests DPAA2_RX_PRINT_PSR_RESULT_FLAG, which nothing sets. Once wired up, its RX_FDIR branch walks rx_vq[0..MAX_RX_QUEUES) and dereferences rxq without a NULL check, but only nb_rx_queues entries exist. Warning: psr_dynfield_offset is never registered, so dpaa2_dev_rx_annot_prefetch(), dpaa2_dev_rx_parse_offset() and struct dpaa2_dyn_rx_protocol_pos are dead. sp_protocol is never assigned, so the GENEVE block is dead. dpaa2_parser_ecpri_extract() and dpaa2_protocol_psr_bit_offset() are unused. Patch 12/13 net/dpaa2: remove unused soft parser driver Warning: rte_flow_create() does not call dpaa2_dev_verify_patterns(). In dpaa2_generic_flow_set() the default case sets ret = -ENOTSUP and breaks only out of the switch. The loop continues, and later item and action calls overwrite ret. With the VXLAN case gone, a pattern eth/ipv4/udp/vxlan/eth is installed with VXLAN ignored and the inner eth handled as in_tunnel. Return from the default case. Info: soft parser leftovers remain: priv->ss_offset, ss_iova, ss_param_iova, sp_protocol, enum dpaa2_ecpri_fafe_type and DPAA2_ECPRI_MAX_EXTRACT_NB. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v6-S2 00/13] net/dpaa2: flow, meter and parser features 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta ` (13 preceding siblings ...) 2026-10-02 16:42 ` [PATCH v5-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger @ 2026-10-06 15:09 ` Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (13 more replies) 14 siblings, 14 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:09 UTC (permalink / raw) To: stephen, dev This is the second of four series upstreaming the missing NXP dpaa2 driver changes. It does not depend on series 1 and can be applied independently. It adds the net/dpaa2 flow, metering and parser features: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, meter and policing, and the flow drop action, with a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - restructure the parser processing, parse tunnel and fragmented packet types, remove the unused soft parser driver and rename the Rx queue flags. Note that patch 12 removes the soft parser driver and, with it, the rte_flow VXLAN and eCPRI pattern items that were only accepted while an SP image was believed to be loaded. Both items are dropped from the dpaa2 feature matrix and a release note is added. Every commit builds cleanly (including the aarch64 DPAA cross build with -Werror) and the series is bisectable. Changes in v6: - patch 10: dropped the inaccurate "no functional change is intended" claim; the commit message now enumerates the functional changes (checksum flag ordering, IPV4/6_EXT/SCTP/ICMP fast-path removal) and the known limitations that need follow-up work, - patch 11: added RTE_PTYPE_L4_FRAG, RTE_PTYPE_TUNNEL_ESP, RTE_PTYPE_TUNNEL_GTPU and RTE_PTYPE_TUNNEL_GTPC to dpaa2_supported_ptypes_get() so the new types are advertised, and OR-ed RTE_PTYPE_L4_UDP into the GTP-U/GTP-C cases since GTP runs over UDP; corrected the commit message to name dpaa2_dev_rx_parse_new(), - patch 12: removed the now-unreachable dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri() handlers, their switch cases, mask descriptors and the VXLAN_HF_VNI helper; dropped the vxlan and ecpri entries from the dpaa2 feature matrix and added a release note; the commit message now explains that the SP must be loaded by firmware at boot, so runtime loading from the PMD never worked, - patch 13: dropped the reference to a Tx confirmation rework that is not part of this series, - patch 5: replaced the stack-allocated err_msg[] buffers whose address was stored in rte_mtr_error with string literals (-Wdangling-pointer). Gagandeep Singh (7): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (4): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 4 +- doc/guides/rel_notes/release_26_11.rst | 18 + drivers/net/dpaa2/dpaa2_ethdev.c | 88 +- drivers/net/dpaa2/dpaa2_ethdev.h | 217 +++- drivers/net/dpaa2/dpaa2_flow.c | 620 +++------ drivers/net/dpaa2/dpaa2_meter.c | 758 +++++++++++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1551 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_recycle.c | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 329 +++-- drivers/net/dpaa2/dpaa2_sparser.c | 137 -- drivers/net/dpaa2/dpaa2_sparser.h | 202 --- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 31 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 2 +- 19 files changed, 3032 insertions(+), 1421 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v6-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta @ 2026-10-06 15:09 ` Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (12 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:09 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, causing the mapping to fail, where the old code would have bumped len up to PAGE_SIZE. The correct mapping size must cover the region from the page-aligned start through offset + len. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) for map_len so that the mmap covers the full requested region regardless of page size. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 02/13] net/dpaa2: set Tx confirmation on device init 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-06 15:09 ` Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta ` (11 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:09 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f211357919..c95704d4ca 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3624,6 +3599,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 03/13] net/dpaa2: support larger burst size 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-06 15:09 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (10 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:09 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (2 preceding siblings ...) 2026-10-06 15:09 ` [PATCH v6-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta ` (9 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 05/13] net/dpaa2: support meter and policing 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (3 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta ` (8 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API. Meters map one-to-one to Rx TCs and are programmed via dpni_set_rx_tc_policing(). Additional corrections over the initial implementation -- - byte-mode rates converted correctly: bytes/s / 125 = Kbps - packet-mode rates passed unchanged to firmware - hardware programmed at create/update; policing disabled at destroy - mtr_id validated against num_rx_tc before use - color_aware capability cleared (FD[DROPP] not handled) - duplicate-ID check and insertion both under meter_lock - removed misleading "Rate limitation" entry from features/dpaa2.ini Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/dpaa2.rst | 1 + doc/guides/rel_notes/release_26_11.rst | 5 + drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_ethdev.h | 29 + drivers/net/dpaa2/dpaa2_meter.c | 758 +++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 23 +- drivers/net/dpaa2/meson.build | 1 + 7 files changed, 815 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index ae8b32af2c..faee3a72a2 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -407,6 +407,7 @@ Features of the DPAA2 PMD are: - Link flow control - Scattered and gather for TX and RX - Rx queue interrupts +- Traffic metering and policing - :ref:`dpaa2_dptmapi` diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index c8cc86295d..869f5a4adc 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -55,6 +55,11 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Updated NXP DPAA2 net driver.** + + * Added Tx queue based flow control and confirmation queue handling. + * Added software parser based packet dump for debugging. + * Added support for traffic metering and policing (rte_mtr API). Removed Items ------------- diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index c95704d4ca..d23c73b21d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3320,6 +3320,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, @@ -3543,6 +3544,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->num_channels = attr.num_channels; priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..e329111c0b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + bool red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -411,6 +435,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -456,6 +481,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -548,6 +576,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..9ad796e8c5 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,758 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +/* + * color_aware mode is not yet implemented: the firmware color input from + * FD[DROPP] is not read or acted upon. Advertise only blind (non-aware) + * trTCM variants until color-aware handling is added. + */ +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = false, + .color_aware_trtcm_rfc4115_supported = false, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +/* + * Program the DPNI policing HW for the given TC. + * profile->cir and profile->pir are stored in the rte_mtr units: + * byte mode: bytes/s -> convert to Kbps (divide by 125) + * packet mode: packets/s -> pass through unchanged + * cbs/pbs are in bytes or packets and fit in uint32_t; the caller must + * verify this before storing in the profile. + */ +static int +dpaa2_mtr_hw_program(struct rte_eth_dev *dev, + uint32_t mtr_id, + const struct dpaa2_dev_meter_profile *profile, + const struct dpaa2_dev_meter_policy *policy) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = priv->hw; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = profile->mode; + cfg.units = profile->policer_unit; + cfg.default_color = DPNI_POLICER_COLOR_GREEN; + + if (policy->red_drop) + cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + + if (profile->policer_unit == DPNI_POLICER_UNIT_BYTES_L3) { + /* rte_mtr rates are bytes/s; DPNI expects Kbps (1 Kbps = 125 B/s). */ + cfg.cir = (uint32_t)(profile->cir / 125); + cfg.eir = (uint32_t)(profile->pir / 125); + } else { + /* Packet mode: rates are packets/s, passed directly. */ + cfg.cir = (uint32_t)profile->cir; + cfg.eir = (uint32_t)profile->pir; + } + cfg.cbs = (uint32_t)profile->cbs; + cfg.ebs = (uint32_t)profile->pbs; + + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) { + DPAA2_PMD_ERR("TC[%u] policing set failed (%d)", mtr_id, ret); + return ret; + } + + return 0; +} + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Policer profile alg not supported!"); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /* Align with DPNI policy. */ + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + dpaa2_profile->profile_id = profile_id; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Meter profile ID already exists!"); + ret = -EEXIST; + goto err; + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_free(dpaa2_policy); + return rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy ID already exists!"); + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + + /* mtr_id maps 1:1 to an Rx TC; validate the range. */ + if (mtr_id >= priv->num_rx_tc) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%u) >= num_rx_tc(%u)!", mtr_id, + priv->num_rx_tc); + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); + } + + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + rte_spinlock_unlock(&priv->meter_lock); + + /* Program the hardware policing configuration for this TC. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + rte_free(meter); + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW policing set failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) { + if (meter != NULL && ret == ENOMEM) + rte_free(meter); + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + } + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv_dev = dev->data->dev_private; + struct fsl_mc_io *dpni = priv_dev->hw; + struct dpaa2_dev_meter *meter; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + /* Disable policing for this TC. */ + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = DPNI_POLICER_MODE_NONE; + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, + priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) + DPAA2_PMD_ERR("TC[%u] policing disable failed (%d)", + mtr_id, ret); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + /* Find the current policy so we can reprogram HW. */ + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == meter->policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current policy ID(%d) not found!", meter->policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new profile. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Policy ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + /* Find the current profile so we can reprogram HW. */ + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == meter->profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current profile ID(%d) not found!", meter->profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new policy. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + RTE_SET_USED(dev); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..d227025e01 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ +#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004 + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1132,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1183,18 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); +int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 06/13] net/dpaa2: support flow drop action 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (4 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta ` (7 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 07/13] net/dpaa2: set default flow miss action per device 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (5 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (6 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global defaulting to 0 and optionally overridden via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. Replace it with a per-device default_flow field in dpaa2_dev_priv, initialised to 0 at probe time, so that each device has its own independent miss-flow setting. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 869f5a4adc..dc938d4519 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -60,6 +60,10 @@ New Features * Added Tx queue based flow control and confirmation queue handling. * Added software parser based packet dump for debugging. * Added support for traffic metering and policing (rte_mtr API). + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id is now fixed at 0. Users who + previously redirected unmatched frames to a specific queue via this + variable must use the rte_flow API instead. Removed Items ------------- diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index d23c73b21d..70f271ec45 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3543,6 +3543,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MIN(priv->fs_entries, + priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); rte_spinlock_init(&priv->meter_lock); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e329111c0b..58a47cd1a2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..03f9193f51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (6 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta ` (5 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are stored via rte_mbuf_sched_set() for use by the scheduler. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 58a47cd1a2..76a04c5858 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 03f9193f51..b7b79929b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..7ba6a4563f 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, 0); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 09/13] net/dpaa2: add minimum key size support 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (7 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (4 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b7b79929b4..f3bb2a858f 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4532,8 +4535,7 @@ dpaa2_flow_entry_size(uint16_t key_max_size) if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 10/13] net/dpaa2: restructure dpaa2 parser processing 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (8 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (3 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move parse-result decoding into dpaa2_parser_decode.h, shared between the flow code and the Rx path. IPV4/6_EXT, SCTP and ICMP ptypes are removed from the rx_parse_new fast-path switch and now go through dpaa2_dev_rx_parse_frc(). Also included in this commit are - Restore Rx timestamp: write annotation->word2 into the dynfield in dpaa2_dev_rx_parse_new() when dpaa2_enable_ts[] is set. - Drop RTE_MBUF_F_RX_FDIR from dpaa2_dev_rx_mbuf_sched_set(): hash.sched overlaps hash.fdir; only hash.sched is written via rte_mbuf_sched_set(). - Parser dump wired up -- set DPAA2_RX_PRINT_PSR_RESULT_FLAG in priv->flags from the DPAA2_PRINT_RX_PARSER_RESULT env var so the dump helper fires. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 +- drivers/net/dpaa2/dpaa2_ethdev.h | 176 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1551 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 323 +++-- 6 files changed, 1938 insertions(+), 555 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 70f271ec45..8b43b2e1eb 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3594,7 +3594,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 76a04c5858..01e5bcbe78 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,18 +207,40 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; +extern bool dpaa2_enable_ts[]; +extern uint64_t dpaa2_timestamp_rx_dynflag; +extern int dpaa2_timestamp_dynfield_offset; + extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ offsetof(struct dpaa2_annot_hdr, word3)) @@ -258,42 +314,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -435,6 +455,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -474,6 +495,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -482,6 +506,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -513,6 +538,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..c57f08ae8c --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1551 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_UNKNOWN; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + /* Non-VLAN IP frames need RTE_PTYPE_L2_ETHER; VLAN frames + * already have L2_ETHER_VLAN set above. + */ + if (ip4_6 && !sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } else { + packet_type |= RTE_PTYPE_L4_NONFRAG; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (!sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 7ba6a4563f..0cfced6525 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,13 +26,7 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" - -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); - -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; +#include "dpaa2_parser_decode.h" static inline rte_mbuf_timestamp_t * dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) @@ -41,6 +35,43 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); } +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} + +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) +{ + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; +} + #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ DPAA2_SET_FD_ADDR(_fd, DPAA2_MBUF_VADDR_TO_IOVA(_mbuf)); \ DPAA2_SET_FD_LEN(_fd, _mbuf->data_len); \ @@ -51,95 +82,121 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) + +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + /* + * FS-marked frame: TC and flow ID are packed in FLC low word. + * Store them via rte_mbuf_sched_set(), which writes hash.sched. + * Do NOT set RTE_MBUF_F_RX_FDIR: hash.sched overlaps hash.fdir + * and rte_mbuf_sched_set() would corrupt any fdir.hi value. + * hash.sched is a scheduler field; FDIR is not claimed here. + */ + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, DPAA2_GET_FD_DROPP(fd)); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + RTE_SET_USED(priv); m->packet_type = RTE_PTYPE_UNKNOWN; + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); + m->packet_type = dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - m->ol_flags |= RTE_MBUF_F_RX_FDIR; - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - rte_mbuf_sched_set(m, flow, tc, 0); - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + *(rte_be64_t *)&word5 = rte_cpu_to_be_64(annotation->word5); + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; m->ol_flags |= dpaa2_timestamp_rx_dynflag; DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + *dpaa2_timestamp_dynfield(m)); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -249,13 +306,15 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); + annotation->word4); + + RTE_SET_USED(priv); if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; @@ -267,9 +326,6 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); - if (dpaa2_enable_ts[mbuf->port]) { *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; @@ -278,7 +334,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -307,8 +363,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -336,12 +391,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -381,13 +438,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -397,7 +463,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -413,9 +479,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -674,6 +741,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -729,15 +797,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -792,18 +861,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -909,18 +972,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -989,7 +1051,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1014,7 +1079,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1041,7 +1109,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1151,12 +1222,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1164,6 +1238,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1314,7 +1389,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1336,7 +1411,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1617,8 +1692,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (9 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (2 subsequent siblings) 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) with new DPAA2_PKT_TYPE_* cases for IPv4/IPv6 fragments, IPsec ESP, and GTP-U/C. GTP-U and GTP-C cases include RTE_PTYPE_L4_UDP to reflect the UDP outer transport. All four new types are also added to dpaa2_supported_ptypes_get() so applications that query supported ptypes see them advertised. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8b43b2e1eb..ab98fda918 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 01e5bcbe78..b3f7b23e01 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 0cfced6525..99e3f496d4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -166,6 +166,42 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 12/13] net/dpaa2: remove unused soft parser driver 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (10 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are also dropped from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_ethdev.h | 1 - drivers/net/dpaa2/dpaa2_flow.c | 564 +------------------------ drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 9 files changed, 10 insertions(+), 935 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..9e24cf3f5b 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -35,7 +35,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y @@ -50,7 +49,6 @@ sctp = Y tcp = Y udp = Y vlan = P -vxlan = Y [rte_flow actions] drop = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index dc938d4519..959193cc92 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -77,6 +77,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * fib: ``RTE_FIB6_IPV6_ADDR_SIZE``, ``RTE_FIB6_MAXDEPTH`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index ab98fda918..5e6ab5ba7e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3723,33 +3722,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index b3f7b23e01..865f2bbe16 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -667,7 +667,6 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); -int dpaa2_soft_parser_loaded(void); void dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f3bb2a858f..f494d038c1 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4905,26 +4377,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5134,15 +4586,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5151,16 +4599,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..1d6f8659be 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v6-S2 13/13] net/dpaa2: rename Rx queue flags 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (11 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-06 15:10 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 13 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-06 15:10 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 5e6ab5ba7e..75881608bf 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3479,7 +3479,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3586,7 +3586,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 865f2bbe16..fbedd9bec7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,10 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) + +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 99e3f496d4..05f885d735 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -901,7 +901,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1173,7 +1173,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta ` (12 preceding siblings ...) 2026-10-06 15:10 ` [PATCH v6-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (14 more replies) 13 siblings, 15 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev This is the second of four series upstreaming the missing NXP dpaa2 driver changes. It does not depend on series 1 and can be applied independently. It adds the net/dpaa2 flow, metering and parser features: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, meter and policing, and the flow drop action, with a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - restructure the parser processing, parse tunnel and fragmented packet types, remove the unused soft parser driver and rename the Rx queue flags. Note that patch 12 removes the soft parser driver and, with it, the rte_flow VXLAN and eCPRI pattern items that were only accepted while an SP image was believed to be loaded. Both items are dropped from the dpaa2 feature matrix and a release note is added. Every commit builds cleanly (including the aarch64 DPAA cross build with -Werror) and the series is bisectable. Changes in v7: - rebased on next-net to resolve apply conflicts reported by patchwork. Changes in v6: - patch 10: dropped the inaccurate "no functional change is intended" claim; the commit message now enumerates the functional changes (checksum flag ordering, IPV4/6_EXT/SCTP/ICMP fast-path removal) and the known limitations that need follow-up work, - patch 11: added RTE_PTYPE_L4_FRAG, RTE_PTYPE_TUNNEL_ESP, RTE_PTYPE_TUNNEL_GTPU and RTE_PTYPE_TUNNEL_GTPC to dpaa2_supported_ptypes_get() so the new types are advertised, and OR-ed RTE_PTYPE_L4_UDP into the GTP-U/GTP-C cases since GTP runs over UDP; corrected the commit message to name dpaa2_dev_rx_parse_new(), - patch 12: removed the now-unreachable dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri() handlers, their switch cases, mask descriptors and the VXLAN_HF_VNI helper; dropped the vxlan and ecpri entries from the dpaa2 feature matrix and added a release note; the commit message now explains that the SP must be loaded by firmware at boot, so runtime loading from the PMD never worked, - patch 13: dropped the reference to a Tx confirmation rework that is not part of this series, - patch 5: replaced the stack-allocated err_msg[] buffers whose address was stored in rte_mtr_error with string literals (-Wdangling-pointer). Gagandeep Singh (7): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (4): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 4 +- doc/guides/rel_notes/release_26_11.rst | 18 + drivers/net/dpaa2/dpaa2_ethdev.c | 88 +- drivers/net/dpaa2/dpaa2_ethdev.h | 217 +++- drivers/net/dpaa2/dpaa2_flow.c | 620 +++------ drivers/net/dpaa2/dpaa2_meter.c | 758 +++++++++++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1551 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_recycle.c | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 329 +++-- drivers/net/dpaa2/dpaa2_sparser.c | 137 -- drivers/net/dpaa2/dpaa2_sparser.h | 202 --- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 31 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 2 +- 19 files changed, 3032 insertions(+), 1421 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v7-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (13 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, causing the mapping to fail, where the old code would have bumped len up to PAGE_SIZE. The correct mapping size must cover the region from the page-aligned start through offset + len. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) for map_len so that the mmap covers the full requested region regardless of page size. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 02/13] net/dpaa2: set Tx confirmation on device init 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta ` (12 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 03/13] net/dpaa2: support larger burst size 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (11 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (2 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta ` (10 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 05/13] net/dpaa2: support meter and policing 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (3 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta ` (9 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API. Meters map one-to-one to Rx TCs and are programmed via dpni_set_rx_tc_policing(). Additional corrections over the initial implementation -- - byte-mode rates converted correctly: bytes/s / 125 = Kbps - packet-mode rates passed unchanged to firmware - hardware programmed at create/update; policing disabled at destroy - mtr_id validated against num_rx_tc before use - color_aware capability cleared (FD[DROPP] not handled) - duplicate-ID check and insertion both under meter_lock - removed misleading "Rate limitation" entry from features/dpaa2.ini Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/dpaa2.rst | 1 + doc/guides/rel_notes/release_26_11.rst | 5 + drivers/net/dpaa2/dpaa2_ethdev.c | 2 + drivers/net/dpaa2/dpaa2_ethdev.h | 29 + drivers/net/dpaa2/dpaa2_meter.c | 758 +++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 23 +- drivers/net/dpaa2/meson.build | 1 + 7 files changed, 815 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index 2928575208..69d111e3ab 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -407,6 +407,7 @@ Features of the DPAA2 PMD are: - Link flow control - Scattered and gather for TX and RX - Rx queue interrupts +- Traffic metering and policing - :ref:`dpaa2_dptmapi` diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..b1ebd508fd 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -20,6 +20,11 @@ DPDK Release 26.11 ninja -C build doc xdg-open build/doc/guides/html/rel_notes/release_26_11.html +* **Updated NXP DPAA2 net driver.** + + * Added Tx queue based flow control and confirmation queue handling. + * Added software parser based packet dump for debugging. + * Added support for traffic metering and policing (rte_mtr API). New Features ------------ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..5f1e832ce3 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3317,6 +3317,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, @@ -3540,6 +3541,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->num_channels = attr.num_channels; priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..e329111c0b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + bool red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -411,6 +435,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -456,6 +481,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -548,6 +576,7 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..9ad796e8c5 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,758 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +/* + * color_aware mode is not yet implemented: the firmware color input from + * FD[DROPP] is not read or acted upon. Advertise only blind (non-aware) + * trTCM variants until color-aware handling is added. + */ +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = false, + .color_aware_trtcm_rfc4115_supported = false, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +/* + * Program the DPNI policing HW for the given TC. + * profile->cir and profile->pir are stored in the rte_mtr units: + * byte mode: bytes/s -> convert to Kbps (divide by 125) + * packet mode: packets/s -> pass through unchanged + * cbs/pbs are in bytes or packets and fit in uint32_t; the caller must + * verify this before storing in the profile. + */ +static int +dpaa2_mtr_hw_program(struct rte_eth_dev *dev, + uint32_t mtr_id, + const struct dpaa2_dev_meter_profile *profile, + const struct dpaa2_dev_meter_policy *policy) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = priv->hw; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = profile->mode; + cfg.units = profile->policer_unit; + cfg.default_color = DPNI_POLICER_COLOR_GREEN; + + if (policy->red_drop) + cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + + if (profile->policer_unit == DPNI_POLICER_UNIT_BYTES_L3) { + /* rte_mtr rates are bytes/s; DPNI expects Kbps (1 Kbps = 125 B/s). */ + cfg.cir = (uint32_t)(profile->cir / 125); + cfg.eir = (uint32_t)(profile->pir / 125); + } else { + /* Packet mode: rates are packets/s, passed directly. */ + cfg.cir = (uint32_t)profile->cir; + cfg.eir = (uint32_t)profile->pir; + } + cfg.cbs = (uint32_t)profile->cbs; + cfg.ebs = (uint32_t)profile->pbs; + + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) { + DPAA2_PMD_ERR("TC[%u] policing set failed (%d)", mtr_id, ret); + return ret; + } + + return 0; +} + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Policer profile alg not supported!"); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /* Align with DPNI policy. */ + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + dpaa2_profile->profile_id = profile_id; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Meter profile ID already exists!"); + ret = -EEXIST; + goto err; + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_free(dpaa2_policy); + return rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy ID already exists!"); + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + + /* mtr_id maps 1:1 to an Rx TC; validate the range. */ + if (mtr_id >= priv->num_rx_tc) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%u) >= num_rx_tc(%u)!", mtr_id, + priv->num_rx_tc); + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); + } + + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + rte_spinlock_unlock(&priv->meter_lock); + + /* Program the hardware policing configuration for this TC. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + rte_free(meter); + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW policing set failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) { + if (meter != NULL && ret == ENOMEM) + rte_free(meter); + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + } + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv_dev = dev->data->dev_private; + struct fsl_mc_io *dpni = priv_dev->hw; + struct dpaa2_dev_meter *meter; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + /* Disable policing for this TC. */ + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = DPNI_POLICER_MODE_NONE; + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, + priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) + DPAA2_PMD_ERR("TC[%u] policing disable failed (%d)", + mtr_id, ret); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + /* Find the current policy so we can reprogram HW. */ + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == meter->policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current policy ID(%d) not found!", meter->policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter->profile_id = profile_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new profile. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Policy ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + /* Find the current profile so we can reprogram HW. */ + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == meter->profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current profile ID(%d) not found!", meter->profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + meter->policy_id = policy_id; + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new policy. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + RTE_SET_USED(dev); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..d227025e01 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,11 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ +#define DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS 0x00000004 + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1132,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1183,18 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); +int dpni_set_rx_tc_policing_v1(struct fsl_mc_io *mc_io, + uint32_t cmd_flags, + uint16_t token, + uint8_t tc_id, + const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 06/13] net/dpaa2: support flow drop action 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (4 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta ` (8 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 07/13] net/dpaa2: set default flow miss action per device 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (5 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (7 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global defaulting to 0 and optionally overridden via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. Replace it with a per-device default_flow field in dpaa2_dev_priv, initialised to 0 at probe time, so that each device has its own independent miss-flow setting. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index b1ebd508fd..63342b855f 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -25,6 +25,10 @@ DPDK Release 26.11 * Added Tx queue based flow control and confirmation queue handling. * Added software parser based packet dump for debugging. * Added support for traffic metering and policing (rte_mtr API). + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id is now fixed at 0. Users who + previously redirected unmatched frames to a specific queue via this + variable must use the rte_flow API instead. New Features ------------ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 5f1e832ce3..b1bb080fc7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3540,6 +3540,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MIN(priv->fs_entries, + priv->dist_queues) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); rte_spinlock_init(&priv->meter_lock); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index e329111c0b..58a47cd1a2 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..03f9193f51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (6 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta ` (6 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are stored via rte_mbuf_sched_set() for use by the scheduler. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 58a47cd1a2..76a04c5858 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 03f9193f51..b7b79929b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..7ba6a4563f 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, 0); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 09/13] net/dpaa2: add minimum key size support 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (7 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (5 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b7b79929b4..f3bb2a858f 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4532,8 +4535,7 @@ dpaa2_flow_entry_size(uint16_t key_max_size) if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 10/13] net/dpaa2: restructure dpaa2 parser processing 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (8 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (4 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move parse-result decoding into dpaa2_parser_decode.h, shared between the flow code and the Rx path. IPV4/6_EXT, SCTP and ICMP ptypes are removed from the rx_parse_new fast-path switch and now go through dpaa2_dev_rx_parse_frc(). Also included in this commit are - Restore Rx timestamp: write annotation->word2 into the dynfield in dpaa2_dev_rx_parse_new() when dpaa2_enable_ts[] is set. - Drop RTE_MBUF_F_RX_FDIR from dpaa2_dev_rx_mbuf_sched_set(): hash.sched overlaps hash.fdir; only hash.sched is written via rte_mbuf_sched_set(). - Parser dump wired up -- set DPAA2_RX_PRINT_PSR_RESULT_FLAG in priv->flags from the DPAA2_PRINT_RX_PARSER_RESULT env var so the dump helper fires. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 +- drivers/net/dpaa2/dpaa2_ethdev.h | 176 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1551 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 323 +++-- 6 files changed, 1938 insertions(+), 555 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index b1bb080fc7..5c6c47c833 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3591,7 +3591,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 76a04c5858..01e5bcbe78 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,18 +207,40 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; +extern bool dpaa2_enable_ts[]; +extern uint64_t dpaa2_timestamp_rx_dynflag; +extern int dpaa2_timestamp_dynfield_offset; + extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ offsetof(struct dpaa2_annot_hdr, word3)) @@ -258,42 +314,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -435,6 +455,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -474,6 +495,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -482,6 +506,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -513,6 +538,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..c57f08ae8c --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1551 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_UNKNOWN; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + /* Non-VLAN IP frames need RTE_PTYPE_L2_ETHER; VLAN frames + * already have L2_ETHER_VLAN set above. + */ + if (ip4_6 && !sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } else { + packet_type |= RTE_PTYPE_L4_NONFRAG; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (!sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 7ba6a4563f..0cfced6525 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,13 +26,7 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" - -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); - -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; +#include "dpaa2_parser_decode.h" static inline rte_mbuf_timestamp_t * dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) @@ -41,6 +35,43 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); } +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} + +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) +{ + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; +} + #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ DPAA2_SET_FD_ADDR(_fd, DPAA2_MBUF_VADDR_TO_IOVA(_mbuf)); \ DPAA2_SET_FD_LEN(_fd, _mbuf->data_len); \ @@ -51,95 +82,121 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) + +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + /* + * FS-marked frame: TC and flow ID are packed in FLC low word. + * Store them via rte_mbuf_sched_set(), which writes hash.sched. + * Do NOT set RTE_MBUF_F_RX_FDIR: hash.sched overlaps hash.fdir + * and rte_mbuf_sched_set() would corrupt any fdir.hi value. + * hash.sched is a scheduler field; FDIR is not claimed here. + */ + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + rte_mbuf_sched_set(m, flow, tc, DPAA2_GET_FD_DROPP(fd)); + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + RTE_SET_USED(priv); m->packet_type = RTE_PTYPE_UNKNOWN; + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); + m->packet_type = dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - m->ol_flags |= RTE_MBUF_F_RX_FDIR; - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - rte_mbuf_sched_set(m, flow, tc, 0); - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + *(rte_be64_t *)&word5 = rte_cpu_to_be_64(annotation->word5); + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; m->ol_flags |= dpaa2_timestamp_rx_dynflag; DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + *dpaa2_timestamp_dynfield(m)); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -249,13 +306,15 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); + annotation->word4); + + RTE_SET_USED(priv); if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; @@ -267,9 +326,6 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); - if (dpaa2_enable_ts[mbuf->port]) { *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; @@ -278,7 +334,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -307,8 +363,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -336,12 +391,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -381,13 +438,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -397,7 +463,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -413,9 +479,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -674,6 +741,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -729,15 +797,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -792,18 +861,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -909,18 +972,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -989,7 +1051,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1014,7 +1079,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1041,7 +1109,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1151,12 +1222,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1164,6 +1238,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1314,7 +1389,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1336,7 +1411,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1617,8 +1692,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (9 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (3 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) with new DPAA2_PKT_TYPE_* cases for IPv4/IPv6 fragments, IPsec ESP, and GTP-U/C. GTP-U and GTP-C cases include RTE_PTYPE_L4_UDP to reflect the UDP outer transport. All four new types are also added to dpaa2_supported_ptypes_get() so applications that query supported ptypes see them advertised. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 5c6c47c833..0f8b67def0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 01e5bcbe78..b3f7b23e01 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 0cfced6525..99e3f496d4 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -166,6 +166,42 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 12/13] net/dpaa2: remove unused soft parser driver 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (10 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta ` (2 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are also dropped from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_ethdev.h | 1 - drivers/net/dpaa2/dpaa2_flow.c | 564 +------------------------ drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 9 files changed, 10 insertions(+), 935 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..9e24cf3f5b 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -35,7 +35,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y @@ -50,7 +49,6 @@ sctp = Y tcp = Y udp = Y vlan = P -vxlan = Y [rte_flow actions] drop = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 63342b855f..e5fe55d62b 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -168,6 +168,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * eal: ``__rte_packed`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0f8b67def0..b6b418d4dd 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3720,33 +3719,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index b3f7b23e01..865f2bbe16 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -667,7 +667,6 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); -int dpaa2_soft_parser_loaded(void); void dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f3bb2a858f..f494d038c1 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4905,26 +4377,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5134,15 +4586,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5151,16 +4599,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..1d6f8659be 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v7-S2 13/13] net/dpaa2: rename Rx queue flags 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (11 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-07 6:02 ` Prashant Gupta 2026-10-07 16:25 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-07 6:02 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index b6b418d4dd..ef10e5ac8c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3476,7 +3476,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3583,7 +3583,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 865f2bbe16..fbedd9bec7 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,10 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) + +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 99e3f496d4..05f885d735 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -901,7 +901,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1173,7 +1173,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (12 preceding siblings ...) 2026-10-07 6:02 ` [PATCH v7-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-07 16:25 ` Stephen Hemminger 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-07 16:25 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Wed, 7 Oct 2026 11:32:14 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This is the second of four series upstreaming the missing NXP dpaa2 > driver changes. It does not depend on series 1 and can be applied > independently. It adds the net/dpaa2 flow, metering and parser features: > > - fix an integer overflow in the CCSR region mapping, > - set Tx confirmation on device init and support a larger burst size, > - support MPLS and PPPoE flow distribution, meter and policing, and the > flow drop action, with a per-device default flow miss action, > - identify Rx mbuf hash information by FLC and add minimum key size > support, > - restructure the parser processing, parse tunnel and fragmented packet > types, remove the unused soft parser driver and rename the Rx queue > flags. > > Note that patch 12 removes the soft parser driver and, with it, the > rte_flow VXLAN and eCPRI pattern items that were only accepted while an > SP image was believed to be loaded. Both items are dropped from the dpaa2 > feature matrix and a release note is added. Ran manual review with AI and looked at the output, boiled the results down to these issues: Review: [PATCH v7-S2 00/13] net/dpaa2 updates Applies to main and on top of S1. Patch 10 (parser restructure) got only a light pass. Patches not listed below have no findings. [PATCH 05/13] net/dpaa2: support meter and policing Warning: dpaa2_mtr_meter_create() drops meter_lock around dpaa2_mtr_hw_program() and re-takes it to insert. If control operations can be concurrent, there is a race here: two creates with the same mtr_id both pass the duplicate check, and a profile or policy can be deleted while hw_program uses it. If they are not allowed (the usual ethdev rule), what is the point of meter_lock? Nothing in the Rx/Tx path touches the meter lists. Either hold the lock across check, program and insert, or drop it. Error: meter state leaks on close. dpaa2_dev_close() never frees priv->profiles, priv->policies or priv->meters. Add a dpaa2_mtr_deinit() and call it next to dpaa2_tm_deinit(): void dpaa2_mtr_deinit(struct rte_eth_dev *dev) { struct dpaa2_dev_priv *priv = dev->data->dev_private; struct dpaa2_dev_meter *m; ... rte_spinlock_lock(&priv->meter_lock); while ((m = LIST_FIRST(&priv->meters)) != NULL) { LIST_REMOVE(m, next); rte_free(m); } /* same for priv->policies and priv->profiles */ rte_spinlock_unlock(&priv->meter_lock); } Warning: cbs/pbs (and pir/cir in packet mode) are cast to uint32_t in dpaa2_mtr_hw_program() without a range check. Reject at profile_add: if (p->cbs > UINT32_MAX || p->pbs > UINT32_MAX) return -rte_mtr_error_set(error, EINVAL, RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, "burst size too large"); Warning: profile_update and policy_update set meter->profile_id / policy_id before dpaa2_mtr_hw_program(). If the MC command fails, software points at the new profile while hardware runs the old one. Commit the id only on success: ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); if (ret) return -rte_mtr_error_set(error, -ret, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "HW policing set failed"); meter->profile_id = profile_id; Warning: capabilities advertise n_max = num_rx_tc even when the DPNI was created without DPNI_OPT_HAS_POLICING. Return ENOTSUP from capabilities_get and meter_create in that case: if (!(priv->options & DPNI_OPT_HAS_POLICING)) return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, "policing not enabled in DPNI"); Info: leftovers. dpni_set_rx_tc_policing_v1() is declared but not defined. DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS is unused. Release notes (05/13, 07/13, 12/13) Error: the "Updated NXP DPAA2 net driver" block is added above the "New Features" heading, in the template header. There is already an "Updated NXP DPAA2 ethernet driver" entry under New Features; put the bullets there. Drop "Tx queue based flow control" and "software parser based packet dump". Neither is added by this series, and 12/13 removes the soft parser. [PATCH 07/13] net/dpaa2: set default flow miss action per device Warning: the commit message and release note say the miss flow id is now 0, but the code sets priv->default_flow = RTE_MIN(priv->fs_entries, priv->dist_queues) - 1; which is the last queue. Fix whichever is wrong. If fs_entries can be 0 this also underflows to 0xffff. [PATCH 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Warning: FS frames are reported with RTE_MBUF_F_RX_FDIR plus rte_mbuf_sched_set(). hash.sched is a Tx scheduler field. 10/13 then removes the FDIR flag, so the final state sets no flag at all and applications cannot tell hash.sched from hash.rss. Use the standard FDIR ID reporting in this patch and leave it alone in 10/13: m->ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID; m->hash.fdir.hi = (tc << 16) | flow; [PATCH 09/13] net/dpaa2: add minimum key size support Info: the removed comment says the MC only supports a fixed 56 byte entry size. Say in the commit message which MC/DPNI version accepts 24, and if older firmware is still supported gate it like 03/13: if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || dpaa2_dev_cmp_dpni_ver(priv, X, Y) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; [PATCH 10/13] net/dpaa2: restructure dpaa2 parser processing Warning: the commit message lists fixes to earlier patches in the same series ("Restore Rx timestamp", "Drop RTE_MBUF_F_RX_FDIR"). Fold each into the patch that introduced the problem so every commit is correct on its own. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v8-S2 00/13] net/dpaa2 updates 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta ` (13 preceding siblings ...) 2026-10-07 16:25 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (14 more replies) 14 siblings, 15 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev This is the second of four series upstreaming the missing NXP dpaa2 driver changes. It does not depend on series 1 and can be applied independently. Changes in v8: - Address review comments for meter and policing support. - Add meter resource cleanup during device close. - Add policing capability checks. - Validate burst size ranges before hardware programming. - Fix software/hardware state consistency on profile/policy updates. - Clarify and guard default flow-miss handling. - Use standard FDIR reporting for flow-steered packets. - Document and gate minimum DPNI version for 24-byte flow keys. - Fold parser fixups into originating patches. - Remove unused VXLAN offset helper following soft parser removal. - Update release notes placement and content. Series overview: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, meter and policing, and the flow drop action, with a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - restructure parser processing, parse tunnel and fragmented packet types, remove the unused soft parser driver and rename Rx queue flags. Gagandeep Singh (7): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (4): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 4 +- doc/guides/rel_notes/release_26_11.rst | 18 + drivers/net/dpaa2/dpaa2_ethdev.c | 89 +- drivers/net/dpaa2/dpaa2_ethdev.h | 218 +++- drivers/net/dpaa2/dpaa2_flow.c | 633 +++------ drivers/net/dpaa2/dpaa2_meter.c | 814 ++++++++++++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1549 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_recycle.c | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 399 ++++-- drivers/net/dpaa2/dpaa2_sparser.c | 137 -- drivers/net/dpaa2/dpaa2_sparser.h | 202 --- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 25 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 2 +- 19 files changed, 3134 insertions(+), 1452 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v8-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (13 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, causing the mapping to fail, where the old code would have bumped len up to PAGE_SIZE. The correct mapping size must cover the region from the page-aligned start through offset + len. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) for map_len so that the mmap covers the full requested region regardless of page size. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 02/13] net/dpaa2: set Tx confirmation on device init 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta ` (12 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 03/13] net/dpaa2: support larger burst size 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (11 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (2 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta ` (10 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 05/13] net/dpaa2: support meter and policing 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (3 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta ` (9 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API. Meters map one-to-one to Rx TCs and are programmed via dpni_set_rx_tc_policing(). Additional corrections over the initial implementation -- - byte-mode rates converted correctly: bytes/s / 125 = Kbps - packet-mode rates passed unchanged to firmware - hardware programmed at create/update; policing disabled at destroy - mtr_id validated against num_rx_tc before use - color_aware capability cleared (FD[DROPP] not handled) - duplicate-ID check and insertion both under meter_lock - removed misleading "Rate limitation" entry from features/dpaa2.ini Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/dpaa2.rst | 1 + doc/guides/rel_notes/release_26_11.rst | 5 + drivers/net/dpaa2/dpaa2_ethdev.c | 3 + drivers/net/dpaa2/dpaa2_ethdev.h | 30 + drivers/net/dpaa2/dpaa2_meter.c | 814 +++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 17 +- drivers/net/dpaa2/meson.build | 1 + 7 files changed, 867 insertions(+), 4 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index 2928575208..69d111e3ab 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -407,6 +407,7 @@ Features of the DPAA2 PMD are: - Link flow control - Scattered and gather for TX and RX - Rx queue interrupts +- Traffic metering and policing - :ref:`dpaa2_dptmapi` diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..b1ebd508fd 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -20,6 +20,11 @@ DPDK Release 26.11 ninja -C build doc xdg-open build/doc/guides/html/rel_notes/release_26_11.html +* **Updated NXP DPAA2 net driver.** + + * Added Tx queue based flow control and confirmation queue handling. + * Added software parser based packet dump for debugging. + * Added support for traffic metering and policing (rte_mtr API). New Features ------------ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..10f9a90639 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1665,6 +1665,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) } dpaa2_tm_deinit(dev); + dpaa2_mtr_deinit(dev); dpaa2_flow_clean(dev); /* Clean the device first */ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); @@ -3317,6 +3318,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, @@ -3540,6 +3542,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->num_channels = attr.num_channels; priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..20817c6b37 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + bool red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -411,6 +435,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -456,6 +481,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -548,6 +576,8 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +void dpaa2_mtr_deinit(struct rte_eth_dev *dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..9611413144 --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,814 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +/* + * color_aware mode is not yet implemented: the firmware color input from + * FD[DROPP] is not read or acted upon. Advertise only blind (non-aware) + * trTCM variants until color-aware handling is added. + */ +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = false, + .color_aware_trtcm_rfc4115_supported = false, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +/* + * Program the DPNI policing HW for the given TC. + * profile->cir and profile->pir are stored in the rte_mtr units: + * byte mode: bytes/s -> convert to Kbps (divide by 125) + * packet mode: packets/s -> pass through unchanged + * cbs/pbs are in bytes or packets and fit in uint32_t; the caller must + * verify this before storing in the profile. + */ +static int +dpaa2_mtr_hw_program(struct rte_eth_dev *dev, + uint32_t mtr_id, + const struct dpaa2_dev_meter_profile *profile, + const struct dpaa2_dev_meter_policy *policy) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = priv->hw; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = profile->mode; + cfg.units = profile->policer_unit; + cfg.default_color = DPNI_POLICER_COLOR_GREEN; + + if (policy->red_drop) + cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + + if (profile->policer_unit == DPNI_POLICER_UNIT_BYTES_L3) { + /* rte_mtr rates are bytes/s; DPNI expects Kbps (1 Kbps = 125 B/s). */ + cfg.cir = (uint32_t)(profile->cir / 125); + cfg.eir = (uint32_t)(profile->pir / 125); + } else { + /* Packet mode: rates are packets/s, passed directly. */ + cfg.cir = (uint32_t)profile->cir; + cfg.eir = (uint32_t)profile->pir; + } + cfg.cbs = (uint32_t)profile->cbs; + cfg.ebs = (uint32_t)profile->pbs; + + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) { + DPAA2_PMD_ERR("TC[%u] policing set failed (%d)", mtr_id, ret); + return ret; + } + + return 0; +} + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + if (!(priv->options & DPNI_OPT_HAS_POLICING)) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "policing not enabled in DPNI"); + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Policer profile alg not supported!"); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /* Align with DPNI policy. */ + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + /* Reject burst sizes that do not fit in the HW uint32_t fields. */ + if (dpaa2_profile->cbs > UINT32_MAX || + dpaa2_profile->pbs > UINT32_MAX) { + rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "burst size too large"); + ret = -EINVAL; + goto err; + } + + /* Reject burst sizes that do not fit in the HW uint32_t fields. */ + if (dpaa2_profile->cbs > UINT32_MAX || + dpaa2_profile->pbs > UINT32_MAX) { + rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "burst size too large"); + ret = -EINVAL; + goto err; + } + + dpaa2_profile->profile_id = profile_id; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Meter profile ID already exists!"); + ret = -EEXIST; + goto err; + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_free(dpaa2_policy); + return rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy ID already exists!"); + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + + if (!(priv->options & DPNI_OPT_HAS_POLICING)) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "policing not enabled in DPNI"); + + /* mtr_id maps 1:1 to an Rx TC; validate the range. */ + if (mtr_id >= priv->num_rx_tc) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%u) >= num_rx_tc(%u)!", mtr_id, + priv->num_rx_tc); + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); + } + + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + rte_spinlock_unlock(&priv->meter_lock); + + /* Program the hardware policing configuration for this TC. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + rte_free(meter); + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW policing set failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) { + if (meter != NULL && ret == ENOMEM) + rte_free(meter); + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + } + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv_dev = dev->data->dev_private; + struct fsl_mc_io *dpni = priv_dev->hw; + struct dpaa2_dev_meter *meter; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + /* Disable policing for this TC. */ + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = DPNI_POLICER_MODE_NONE; + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, + priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) + DPAA2_PMD_ERR("TC[%u] policing disable failed (%d)", + mtr_id, ret); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + /* Find the current policy so we can reprogram HW. */ + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == meter->policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current policy ID(%d) not found!", meter->policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new profile. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + /* Commit the new profile id only after HW succeeded. */ + meter->profile_id = profile_id; + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Policy ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + /* Find the current profile so we can reprogram HW. */ + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == meter->profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current profile ID(%d) not found!", meter->profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new policy. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + /* Commit the new policy id only after HW succeeded. */ + meter->policy_id = policy_id; + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +void +dpaa2_mtr_deinit(struct rte_eth_dev *dev) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *m; + struct dpaa2_dev_meter_policy *p; + struct dpaa2_dev_meter_profile *pf; + + rte_spinlock_lock(&priv->meter_lock); + while ((m = LIST_FIRST(&priv->meters)) != NULL) { + LIST_REMOVE(m, next); + rte_free(m); + } + while ((p = LIST_FIRST(&priv->policies)) != NULL) { + LIST_REMOVE(p, next); + rte_free(p); + } + while ((pf = LIST_FIRST(&priv->profiles)) != NULL) { + LIST_REMOVE(pf, next); + rte_free(pf); + } + rte_spinlock_unlock(&priv->meter_lock); +} + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + RTE_SET_USED(dev); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..aff0deee08 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,10 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1131,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1182,13 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 06/13] net/dpaa2: support flow drop action 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (4 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta ` (8 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 07/13] net/dpaa2: set default flow miss action per device 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (5 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (7 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global defaulting to 0 and optionally overridden via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. Replace it with a per-device default_flow field in dpaa2_dev_priv, initialised to the lowest-priority flow ID (min(fs_entries, dist_queues) - 1) at probe time, so that each device has its own independent miss-flow setting. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index b1ebd508fd..0035a9d5a1 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -25,6 +25,10 @@ DPDK Release 26.11 * Added Tx queue based flow control and confirmation queue handling. * Added software parser based packet dump for debugging. * Added support for traffic metering and policing (rte_mtr API). + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id now defaults to the lowest-priority + flow of the device. Users who previously redirected unmatched frames + to a specific queue via this variable must use the rte_flow API instead. New Features ------------ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 10f9a90639..9878e2b06f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3541,6 +3541,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MAX(RTE_MIN(priv->fs_entries, + priv->dist_queues), 1) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); rte_spinlock_init(&priv->meter_lock); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 20817c6b37..2253a27a4b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..03f9193f51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (6 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta ` (6 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are stored via rte_mbuf_sched_set() for use by the scheduler. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 20 +++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 2253a27a4b..ab5bcc34f0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 03f9193f51..b7b79929b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..62565486a7 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,23 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->ol_flags |= + RTE_MBUF_F_RX_FDIR | + RTE_MBUF_F_RX_FDIR_ID; + m->hash.fdir.hi = (tc << 16) | flow; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 09/13] net/dpaa2: add minimum key size support 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (7 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (5 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Support for 24-byte QoS key entries is available from DPNI version 8.7 onwards. For older DPNI versions, the existing 56-byte entry size is retained to maintain compatibility. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b7b79929b4..61a080893d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4519,7 +4522,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4529,11 +4532,11 @@ dpaa2_flow_entry_size(uint16_t key_max_size) return 0; } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || + dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int @@ -4595,7 +4598,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4686,7 +4689,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4977,11 +4980,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 10/13] net/dpaa2: restructure dpaa2 parser processing 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (8 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (4 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move parse-result decoding into dpaa2_parser_decode.h, shared between the flow code and the Rx path. IPV4/6_EXT, SCTP and ICMP ptypes are removed from the rx_parse_new fast-path switch and now go through dpaa2_dev_rx_parse_frc(). Also included in this commit are - Restore Rx timestamp: write annotation->word2 into the dynfield in dpaa2_dev_rx_parse_new() when dpaa2_enable_ts[] is set. - Drop RTE_MBUF_F_RX_FDIR from dpaa2_dev_rx_mbuf_sched_set(): hash.sched overlaps hash.fdir; only hash.sched is written via rte_mbuf_sched_set(). - Parser dump wired up -- set DPAA2_RX_PRINT_PSR_RESULT_FLAG in priv->flags from the DPAA2_PRINT_RX_PARSER_RESULT env var so the dump helper fires. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 +- drivers/net/dpaa2/dpaa2_ethdev.h | 176 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1551 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 410 +++--- 6 files changed, 1990 insertions(+), 590 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 9878e2b06f..88ff5daba4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3592,7 +3592,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index ab5bcc34f0..acf377730a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,18 +207,40 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; +extern bool dpaa2_enable_ts[]; +extern uint64_t dpaa2_timestamp_rx_dynflag; +extern int dpaa2_timestamp_dynfield_offset; + extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ offsetof(struct dpaa2_annot_hdr, word3)) @@ -258,42 +314,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -435,6 +455,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -474,6 +495,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -482,6 +506,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -513,6 +538,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..c57f08ae8c --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1551 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_UNKNOWN; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + /* Non-VLAN IP frames need RTE_PTYPE_L2_ETHER; VLAN frames + * already have L2_ETHER_VLAN set above. + */ + if (ip4_6 && !sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } else { + packet_type |= RTE_PTYPE_L4_NONFRAG; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (!sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 62565486a7..5a5efb8bff 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,13 +26,7 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" - -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); - -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; +#include "dpaa2_parser_decode.h" static inline rte_mbuf_timestamp_t * dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) @@ -41,6 +35,43 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); } +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} + +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) +{ + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; +} + #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ DPAA2_SET_FD_ADDR(_fd, DPAA2_MBUF_VADDR_TO_IOVA(_mbuf)); \ DPAA2_SET_FD_LEN(_fd, _mbuf->data_len); \ @@ -51,102 +82,145 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) +static inline void +dpaa2_dev_rx_mbuf_sched_set(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; - uint32_t flc_lo, tc, flow; - - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); - - m->packet_type = RTE_PTYPE_UNKNOWN; - switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; - break; - case DPAA2_PKT_TYPE_IPV4_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; - break; - case DPAA2_PKT_TYPE_IPV6_UDP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; - break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV4_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; - break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; - break; - default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); - } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - m->ol_flags |= - RTE_MBUF_F_RX_FDIR | - RTE_MBUF_F_RX_FDIR_ID; - m->hash.fdir.hi = (tc << 16) | flow; - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); - } + uint32_t flc_lo, tc, flow; - if (dpaa2_enable_ts[m->port]) { - *dpaa2_timestamp_dynfield(m) = annotation->word2; - m->ol_flags |= dpaa2_timestamp_rx_dynflag; - DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); - } + flc_lo = fd->simple.flc_lo; - DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " - "ol_flags =0x%" PRIx64 "", - frc, m->packet_type, m->ol_flags); + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + + m->ol_flags |= + RTE_MBUF_F_RX_FDIR | + RTE_MBUF_F_RX_FDIR_ID; + m->hash.fdir.hi = (tc << 16) | flow; + + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; + + m->packet_type = RTE_PTYPE_UNKNOWN; + + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } + + switch (frc) { + case DPAA2_PKT_TYPE_IPV4_UDP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + break; + + case DPAA2_PKT_TYPE_IPV4_TCP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; + break; + + case DPAA2_PKT_TYPE_IPV4: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4; + break; + + case DPAA2_PKT_TYPE_IPV6_UDP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; + break; + + case DPAA2_PKT_TYPE_IPV6_TCP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; + break; + + case DPAA2_PKT_TYPE_IPV6: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6; + break; + + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; + break; + + default: + m->packet_type = + dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; + break; + } + + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + + *(rte_be64_t *)&word5 = + rte_cpu_to_be_64(annotation->word5); + + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + + /* RSS / FDIR information from FLC */ + dpaa2_dev_rx_mbuf_sched_set(m, fd); + + if (dpaa2_enable_ts[m->port]) { + *dpaa2_timestamp_dynfield(m) = annotation->word2; + m->ol_flags |= dpaa2_timestamp_rx_dynflag; + + DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", + *dpaa2_timestamp_dynfield(m)); + } + + DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " + "ol_flags =0x%" PRIx64 "", + frc, m->packet_type, m->ol_flags); } static inline uint32_t __rte_hot @@ -251,13 +325,15 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); + annotation->word4); + + RTE_SET_USED(priv); if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; @@ -269,9 +345,6 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); - if (dpaa2_enable_ts[mbuf->port]) { *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; @@ -280,7 +353,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -309,8 +382,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -338,12 +410,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_mbuf_sched_set(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -383,13 +457,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -399,7 +482,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -415,9 +498,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_mbuf_sched_set(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -676,6 +760,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -731,15 +816,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -794,18 +880,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -911,18 +991,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -991,7 +1070,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1016,7 +1098,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1043,7 +1128,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1153,12 +1241,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1166,6 +1257,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1316,7 +1408,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1338,7 +1430,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1619,8 +1711,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (9 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (3 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to identify IPv4/IPv6 fragmented packets, IPsec ESP, and GTP-U/GTP-C packets. Map the corresponding parser summary values to DPDK packet types. GTP-U and GTP-C packets are additionally marked with RTE_PTYPE_L4_UDP to reflect the UDP transport used by the outer tunnel header. Advertise the newly supported packet types through dpaa2_supported_ptypes_get(). Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 16 +++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 41 ++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 88ff5daba4..678a30e683 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index acf377730a..311084a1f0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 5a5efb8bff..56bc4e46be 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -174,8 +174,45 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; default: -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 12/13] net/dpaa2: remove unused soft parser driver 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (10 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-09 10:48 ` Prashant Gupta 2026-10-09 10:49 ` [PATCH v8-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta ` (2 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:48 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are also dropped from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_ethdev.h | 1 - drivers/net/dpaa2/dpaa2_flow.c | 564 +----------------------- drivers/net/dpaa2/dpaa2_parser_decode.h | 2 - drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 10 files changed, 10 insertions(+), 937 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..9e24cf3f5b 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -35,7 +35,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y @@ -50,7 +49,6 @@ sctp = Y tcp = Y udp = Y vlan = P -vxlan = Y [rte_flow actions] drop = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 0035a9d5a1..254fa56905 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -168,6 +168,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * eal: ``__rte_packed`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 678a30e683..a660a925cd 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3721,33 +3720,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 311084a1f0..a0b08bddf4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -668,7 +668,6 @@ int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); void dpaa2_mtr_deinit(struct rte_eth_dev *dev); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); -int dpaa2_soft_parser_loaded(void); void dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 61a080893d..a4575e7314 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4906,26 +4378,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5135,15 +4587,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5152,16 +4600,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h index c57f08ae8c..807439bc9f 100644 --- a/drivers/net/dpaa2/dpaa2_parser_decode.h +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -625,8 +625,6 @@ union __rte_packed_begin dpaa2_faf_h_parse_64b { #define DPAA2_VXLAN_IN_SADDR5_OFFSET \ offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) -#define DPAA2_VXLAN_VNI_OFFSET \ - offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) #define DPAA2_VXLAN_IN_TYPE_OFFSET \ offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) /* Set by SP for vxlan distribution end*/ diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..1d6f8659be 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v8-S2 13/13] net/dpaa2: rename Rx queue flags 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (11 preceding siblings ...) 2026-10-09 10:48 ` [PATCH v8-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-09 10:49 ` Prashant Gupta 2026-10-09 19:09 ` [PATCH v8-S2 00/13] net/dpaa2 updates Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-09 10:49 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index a660a925cd..51a38c2df9 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3477,7 +3477,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3584,7 +3584,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index a0b08bddf4..17c1cb6cea 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,10 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) + +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 56bc4e46be..cbdc698d74 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -921,7 +921,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1193,7 +1193,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v8-S2 00/13] net/dpaa2 updates 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (12 preceding siblings ...) 2026-10-09 10:49 ` [PATCH v8-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-09 19:09 ` Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-09 19:09 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Fri, 9 Oct 2026 16:18:47 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This is the second of four series upstreaming the missing NXP dpaa2 > driver changes. It does not depend on series 1 and can be applied > independently. > > Changes in v8: > - Address review comments for meter and policing support. > - Add meter resource cleanup during device close. > - Add policing capability checks. > - Validate burst size ranges before hardware programming. > - Fix software/hardware state consistency on profile/policy updates. > - Clarify and guard default flow-miss handling. > - Use standard FDIR reporting for flow-steered packets. > - Document and gate minimum DPNI version for 24-byte flow keys. > - Fold parser fixups into originating patches. > - Remove unused VXLAN offset helper following soft parser removal. > - Update release notes placement and content. Although review of S1 was clean and now in next-net, the second part still has open issues: Review: [PATCH v8-S2 00/13] net/dpaa2 updates Applies on top of v7-S1. Most v7 comments are addressed (mtr deinit, policing check, update ordering, FDIR_ID, key size gating, miss flow note). Remaining items below. [PATCH 05/13] net/dpaa2: support meter and policing Error: the burst size check in dpaa2_mtr_profile_add() is pasted twice. Remove one copy. Warning: meter_create still drops meter_lock around dpaa2_mtr_hw_program(). If control operations can be concurrent, there is a race here; if not allowed, what is the point of meter_lock? Either hold it across check, program and insert, or drop the lock. Info: fsl_dpni.h removes DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS but leaves its comment ("Do NOT reset counters generally for policer update") and an extra blank line where the _v1 prototype was. Remove both. Release notes (05/13, 07/13) Error: not changed from v7. The "Updated NXP DPAA2 net driver" block is still above the "New Features" heading, duplicates the existing "Updated NXP DPAA2 ethernet driver" entry, and still lists "Tx queue based flow control" and "software parser based packet dump", which this series does not add (12/13 removes the soft parser). Move the meter and miss flow bullets into the existing entry under New Features: * **Updated NXP DPAA2 ethernet driver.** ... * Added support for traffic metering and policing (rte_mtr API). * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. Use the rte_flow API to steer unmatched frames. [PATCH 10/13] net/dpaa2: restructure dpaa2 parser processing Warning: the new code in dpaa2_rxtx.c is indented with spaces (about 100 lines, e.g. dpaa2_dev_rx_mbuf_sched_set()). Use tabs. Warning: the commit message is stale. It still says "Restore Rx timestamp" and "Drop RTE_MBUF_F_RX_FDIR", but timestamp is already handled at 08/13 and the code now sets RX_FDIR | RX_FDIR_ID. Drop both bullets. Also rename dpaa2_dev_rx_mbuf_sched_set(), it no longer calls rte_mbuf_sched_set(); dpaa2_dev_rx_flc_info() or similar. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v9-S2 00/13] net/dpaa2 updates 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta ` (13 preceding siblings ...) 2026-10-09 19:09 ` [PATCH v8-S2 00/13] net/dpaa2 updates Stephen Hemminger @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (14 more replies) 14 siblings, 15 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev Changes in v9: - Address review comments for meter and policing support. - Add meter resource cleanup during device close. - Add policing capability checks. - Validate burst size ranges before hardware programming. - Fix software/hardware state consistency on profile and policy updates. - Use standard FDIR reporting for flow-steered packets. - Replace global flow miss configuration with a per-device default flow and remove the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. - Document and gate minimum DPNI version requirement for 24-byte flow keys. - Rework parser decode infrastructure and parser-result dumping. - Parse additional tunnel and fragmented packet types. - Fold parser-related fixes into the originating patches. - Remove unused VXLAN offset helpers after soft parser removal. - Move release note updates into the existing DPAA2 ethernet driver entry under New Features. - Fix coding style issues reported during review. Series overview: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, meter and policing, and the flow drop action, with a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - restructure parser processing, parse tunnel and fragmented packet types, remove the unused soft parser driver and rename Rx queue flags. Gagandeep Singh (7): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support meter and policing net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (4): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: restructure dpaa2 parser processing net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/dpaa2.rst | 1 + doc/guides/nics/features/dpaa2.ini | 4 +- doc/guides/rel_notes/release_26_11.rst | 15 +- drivers/net/dpaa2/dpaa2_ethdev.c | 89 +- drivers/net/dpaa2/dpaa2_ethdev.h | 218 +++- drivers/net/dpaa2/dpaa2_flow.c | 633 +++------ drivers/net/dpaa2/dpaa2_meter.c | 804 ++++++++++++ drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1549 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_recycle.c | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 351 +++-- drivers/net/dpaa2/dpaa2_sparser.c | 137 -- drivers/net/dpaa2/dpaa2_sparser.h | 202 --- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 25 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 2 +- 19 files changed, 3096 insertions(+), 1429 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v9-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-13 14:52 ` Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (13 subsequent siblings) 14 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, causing the mapping to fail, where the old code would have bumped len up to PAGE_SIZE. The correct mapping size must cover the region from the page-aligned start through offset + len. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) for map_len so that the mmap covers the full requested region regardless of page size. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v9-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-12 7:04 ` [PATCH v9-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-13 14:52 ` Stephen Hemminger 0 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-13 14:52 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, stable, Hemant Agrawal On Mon, 12 Oct 2026 12:34:32 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > From: Hemant Agrawal <hemant.agrawal@nxp.com> > > In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as > sysconf(_SC_PAGESIZE), which returns a signed long and may be negative > on error. The value was used directly in size_t comparisons and passed > to mmap, causing an integer overflow (Coverity CID 49765682). > > The old round-down "len & PAGE_MASK" ignored the in-page offset: for a > 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, > causing the mapping to fail, where the old code would have bumped len up > to PAGE_SIZE. The correct mapping size must cover the region from the > page-aligned start through offset + len. > > Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, > checking for a non-positive return before use, computing page_mask from > the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) > for map_len so that the mmap covers the full requested region regardless > of page size. The page-aligned start address and the back-pointer offset > are both derived from the same page_mask, keeping the three values > consistent. > > Coverity issue: 49765682 > Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") > Cc: stable@dpdk.org > Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> > --- > drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- > 1 file changed, 15 insertions(+), 8 deletions(-) > > diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c > index f78d12362e..9b6ae3f515 100644 > --- a/drivers/net/dpaa2/dpaa2_recycle.c > +++ b/drivers/net/dpaa2/dpaa2_recycle.c > @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) > void *tmp; > uint64_t start; > uint64_t offset; > + uint64_t page_mask; > + long page_size; > + size_t map_len; > > fd = open("/dev/mem", O_RDWR); Does this driver work with CONFIG_STRICT_DEVMEM and CONFIG_IO_STRICT_DEVMEM? Note it won't work in lockdown mode at all. > if (fd < 0) { > @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) > return NULL; > } > > - start = addr & PAGE_MASK; > + page_size = sysconf(_SC_PAGESIZE); > + if (page_size <= 0) { Something is broken if this happens, should log it? ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v9-S2 02/13] net/dpaa2: set Tx confirmation on device init 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta ` (12 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 03/13] net/dpaa2: support larger burst size 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (11 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (2 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-13 14:54 ` Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta ` (10 subsequent siblings) 14 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v9-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-12 7:04 ` [PATCH v9-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-13 14:54 ` Stephen Hemminger 0 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-13 14:54 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, Gagandeep Singh On Mon, 12 Oct 2026 12:34:35 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > + ret = dpaa2_flow_identify_by_faf(priv, flow, > + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, > + group, &local_cfg); > + if (ret) > + return ret; > + > + (*device_configured) |= local_cfg; Unnecessary extra parenthesis. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v9-S2 05/13] net/dpaa2: support meter and policing 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (3 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-13 14:55 ` Stephen Hemminger ` (2 more replies) 2026-10-12 7:04 ` [PATCH v9-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta ` (9 subsequent siblings) 14 siblings, 3 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the traffic metering and policing (rte_mtr) API. Meters map one-to-one to Rx TCs and are programmed via dpni_set_rx_tc_policing(). Additional corrections over the initial implementation -- - byte-mode rates converted correctly: bytes/s / 125 = Kbps - packet-mode rates passed unchanged to firmware - hardware programmed at create/update; policing disabled at destroy - mtr_id validated against num_rx_tc before use - color_aware capability cleared (FD[DROPP] not handled) - duplicate-ID check and insertion both under meter_lock - removed misleading "Rate limitation" entry from features/dpaa2.ini Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/dpaa2.rst | 1 + doc/guides/rel_notes/release_26_11.rst | 2 +- drivers/net/dpaa2/dpaa2_ethdev.c | 3 + drivers/net/dpaa2/dpaa2_ethdev.h | 30 + drivers/net/dpaa2/dpaa2_meter.c | 804 +++++++++++++++++++++++++ drivers/net/dpaa2/mc/fsl_dpni.h | 17 +- drivers/net/dpaa2/meson.build | 1 + 7 files changed, 853 insertions(+), 5 deletions(-) create mode 100644 drivers/net/dpaa2/dpaa2_meter.c diff --git a/doc/guides/nics/dpaa2.rst b/doc/guides/nics/dpaa2.rst index 2928575208..69d111e3ab 100644 --- a/doc/guides/nics/dpaa2.rst +++ b/doc/guides/nics/dpaa2.rst @@ -407,6 +407,7 @@ Features of the DPAA2 PMD are: - Link flow control - Scattered and gather for TX and RX - Rx queue interrupts +- Traffic metering and policing - :ref:`dpaa2_dptmapi` diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..4522d988ad 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -20,7 +20,6 @@ DPDK Release 26.11 ninja -C build doc xdg-open build/doc/guides/html/rel_notes/release_26_11.html - New Features ------------ @@ -105,6 +104,7 @@ New Features * Added the inner IP header to the RSS hash so tunneled traffic is distributed across the Rx queues. + * Added support for traffic metering and policing (rte_mtr API). * **Updated NXP ENETC4 PMD.** diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..10f9a90639 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1665,6 +1665,7 @@ dpaa2_dev_close(struct rte_eth_dev *dev) } dpaa2_tm_deinit(dev); + dpaa2_mtr_deinit(dev); dpaa2_flow_clean(dev); /* Clean the device first */ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); @@ -3317,6 +3318,7 @@ static struct eth_dev_ops dpaa2_ethdev_ops = { .rxq_info_get = dpaa2_rxq_info_get, .txq_info_get = dpaa2_txq_info_get, .tm_ops_get = dpaa2_tm_ops_get, + .mtr_ops_get = dpaa2_mtr_ops_get, #if defined(RTE_LIBRTE_IEEE1588) .timesync_enable = dpaa2_timesync_enable, .timesync_disable = dpaa2_timesync_disable, @@ -3540,6 +3542,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->num_channels = attr.num_channels; priv->channel_inuse = 0; rte_spinlock_init(&priv->lpbk_qp_lock); + rte_spinlock_init(&priv->meter_lock); /* only if the custom CG is enabled */ if (attr.options & DPNI_OPT_CUSTOM_CG) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..20817c6b37 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -385,6 +385,30 @@ struct extract_s { uint8_t *tc_extract_param[MAX_TCS]; }; +struct dpaa2_dev_meter_profile { + LIST_ENTRY(dpaa2_dev_meter_profile) next; + uint32_t profile_id; + uint64_t cir; + uint64_t cbs; + uint64_t pir; + uint64_t pbs; + enum dpni_policer_mode mode; + enum dpni_policer_unit policer_unit; +}; + +struct dpaa2_dev_meter_policy { + LIST_ENTRY(dpaa2_dev_meter_policy) next; + uint32_t policy_id; + bool red_drop; +}; + +struct dpaa2_dev_meter { + LIST_ENTRY(dpaa2_dev_meter) next; + uint32_t meter_id; + uint32_t profile_id; + uint32_t policy_id; +}; + struct dpaa2_dev_priv { void *hw; int32_t hw_id; @@ -411,6 +435,7 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + rte_spinlock_t meter_lock; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. @@ -456,6 +481,9 @@ struct dpaa2_dev_priv { struct dpaa2_dev_flow *curr; LIST_HEAD(, dpaa2_dev_flow) flows; + LIST_HEAD(, dpaa2_dev_meter_profile) profiles; + LIST_HEAD(, dpaa2_dev_meter_policy) policies; + LIST_HEAD(, dpaa2_dev_meter) meters; LIST_HEAD(nodes, dpaa2_tm_node) nodes; LIST_HEAD(shaper_profiles, dpaa2_tm_shaper_profile) shaper_profiles; }; @@ -548,6 +576,8 @@ int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev, int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); +void dpaa2_mtr_deinit(struct rte_eth_dev *dev); +int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); int dpaa2_soft_parser_loaded(void); void diff --git a/drivers/net/dpaa2/dpaa2_meter.c b/drivers/net/dpaa2/dpaa2_meter.c new file mode 100644 index 0000000000..5ed8c58a3f --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_meter.c @@ -0,0 +1,804 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2025-2026 NXP + */ + +#include <sys/queue.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/mman.h> + +#include <rte_ethdev.h> +#include <rte_log.h> +#include <rte_malloc.h> +#include <rte_flow_driver.h> +#include <rte_tailq.h> +#include <rte_mtr.h> +#include <rte_mtr_driver.h> + +#include <fsl_dpni.h> +#include <fsl_dpkg.h> + +#include <dpaa2_ethdev.h> +#include <dpaa2_pmd_logs.h> + +static char s_err_msg[128]; + +/* + * color_aware mode is not yet implemented: the firmware color input from + * FD[DROPP] is not read or acted upon. Advertise only blind (non-aware) + * trTCM variants until color-aware handling is added. + */ +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { + .color_aware_trtcm_rfc2698_supported = false, + .color_aware_trtcm_rfc4115_supported = false, + .trtcm_rfc2698_byte_mode_supported = true, + .trtcm_rfc2698_packet_mode_supported = true, + .trtcm_rfc4115_byte_mode_supported = true, + .trtcm_rfc4115_packet_mode_supported = true +}; + +/* + * Program the DPNI policing HW for the given TC. + * profile->cir and profile->pir are stored in the rte_mtr units: + * byte mode: bytes/s -> convert to Kbps (divide by 125) + * packet mode: packets/s -> pass through unchanged + * cbs/pbs are in bytes or packets and fit in uint32_t; the caller must + * verify this before storing in the profile. + */ +static int +dpaa2_mtr_hw_program(struct rte_eth_dev *dev, + uint32_t mtr_id, + const struct dpaa2_dev_meter_profile *profile, + const struct dpaa2_dev_meter_policy *policy) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct fsl_mc_io *dpni = priv->hw; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = profile->mode; + cfg.units = profile->policer_unit; + cfg.default_color = DPNI_POLICER_COLOR_GREEN; + + if (policy->red_drop) + cfg.options |= DPNI_POLICER_OPT_DISCARD_RED; + + if (profile->policer_unit == DPNI_POLICER_UNIT_BYTES_L3) { + /* rte_mtr rates are bytes/s; DPNI expects Kbps (1 Kbps = 125 B/s). */ + cfg.cir = (uint32_t)(profile->cir / 125); + cfg.eir = (uint32_t)(profile->pir / 125); + } else { + /* Packet mode: rates are packets/s, passed directly. */ + cfg.cir = (uint32_t)profile->cir; + cfg.eir = (uint32_t)profile->pir; + } + cfg.cbs = (uint32_t)profile->cbs; + cfg.ebs = (uint32_t)profile->pbs; + + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) { + DPAA2_PMD_ERR("TC[%u] policing set failed (%d)", mtr_id, ret); + return ret; + } + + return 0; +} + +static int +dpaa2_mtr_capabilities_get(struct rte_eth_dev *dev, + struct rte_mtr_capabilities *capa, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + + if (capa == NULL) { + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL, + "NULL input parameter"); + } + + if (!(priv->options & DPNI_OPT_HAS_POLICING)) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "policing not enabled in DPNI"); + + rte_spinlock_lock(&priv->meter_lock); + s_dpaa2_mtr_capa.n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.n_shared_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc2698_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_trtcm_rfc4115_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.meter_policy_n_max = priv->num_rx_tc; + s_dpaa2_mtr_capa.shared_n_flows_per_mtr_max = priv->fs_entries; + rte_spinlock_unlock(&priv->meter_lock); + + *capa = s_dpaa2_mtr_capa; + + return 0; +} + +static int +dpaa2_mtr_profile_add(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_meter_profile *profile, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + struct dpaa2_dev_meter_profile *curr; + int ret = 0; + + dpaa2_profile = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_profile), 0); + if (dpaa2_profile == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter profile memory alloc failed!"); + } + if (profile->alg == RTE_MTR_NONE) { + dpaa2_profile->mode = DPNI_POLICER_MODE_PASS_THROUGH; + } else if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_2698; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->mode = DPNI_POLICER_MODE_RFC_4115; + } else { + DPAA2_PMD_ERR("Policer profile alg(%d) not supported!", + profile->alg); + rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "Policer profile alg not supported!"); + ret = -ENOTSUP; + goto err; + } + + if (profile->alg == RTE_MTR_TRTCM_RFC2698) { + dpaa2_profile->cir = profile->trtcm_rfc2698.cir; + dpaa2_profile->cbs = profile->trtcm_rfc2698.cbs; + dpaa2_profile->pir = profile->trtcm_rfc2698.pir; + dpaa2_profile->pbs = profile->trtcm_rfc2698.pbs; + } else if (profile->alg == RTE_MTR_TRTCM_RFC4115) { + dpaa2_profile->cir = profile->trtcm_rfc4115.cir; + dpaa2_profile->cbs = profile->trtcm_rfc4115.cbs; + dpaa2_profile->pir = profile->trtcm_rfc4115.eir; + dpaa2_profile->pbs = profile->trtcm_rfc4115.ebs; + } + + /* Align with DPNI policy. */ + if (!profile->packet_mode) + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_BYTES_L3; + else + dpaa2_profile->policer_unit = DPNI_POLICER_UNIT_FRAMES; + + /* Reject burst sizes that do not fit in the HW uint32_t fields. */ + if (dpaa2_profile->cbs > UINT32_MAX || + dpaa2_profile->pbs > UINT32_MAX) { + rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL, + "burst size too large"); + ret = -EINVAL; + goto err; + } + + dpaa2_profile->profile_id = profile_id; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + NULL, "Meter profile ID already exists!"); + ret = -EEXIST; + goto err; + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->profiles); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->profiles, dpaa2_profile, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + +err: + if (ret != 0) + rte_free(dpaa2_profile); + + return ret; +} + +static int +dpaa2_mtr_policy_add(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_meter_policy_params *policy, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + struct dpaa2_dev_meter_policy *curr; + const struct rte_flow_action *red_action; + bool red_drop = false; + + if (policy->actions[RTE_COLOR_GREEN] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN, NULL, + "Meter green policy action not supported!"); + } + if (policy->actions[RTE_COLOR_YELLOW] != NULL) { + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW, NULL, + "Meter yellow policy action not supported!"); + } + + red_action = policy->actions[RTE_COLOR_RED]; + + if (red_action != NULL) { + if (red_action->type == RTE_FLOW_ACTION_TYPE_DROP) { + red_drop = true; + } else if (red_action->type != RTE_FLOW_ACTION_TYPE_PASSTHRU) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter red policy action(%d) NOT supported!", + red_action->type); + return rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED, NULL, + s_err_msg); + } + } + + dpaa2_policy = rte_zmalloc(NULL, + sizeof(struct dpaa2_dev_meter_policy), 0); + if (dpaa2_policy == NULL) { + return rte_mtr_error_set(error, ENOMEM, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "Meter policy memory alloc failed!"); + } + + dpaa2_policy->policy_id = policy_id; + dpaa2_policy->red_drop = red_drop; + + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + rte_free(dpaa2_policy); + return rte_mtr_error_set(error, EEXIST, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy ID already exists!"); + } + curr = LIST_NEXT(curr, next); + } + + curr = LIST_FIRST(&priv->policies); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->policies, dpaa2_policy, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static struct rte_flow_meter_profile * +dpaa2_mtr_profile_get(struct rte_eth_dev *dev, + uint32_t meter_profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_profile = LIST_FIRST(&priv->profiles); + while (dpaa2_profile != NULL) { + if (dpaa2_profile->profile_id == meter_profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_profile *)dpaa2_profile; + } + dpaa2_profile = LIST_NEXT(dpaa2_profile, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static struct rte_flow_meter_policy * +dpaa2_mtr_policy_get(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy; + + RTE_SET_USED(error); + + rte_spinlock_lock(&priv->meter_lock); + dpaa2_policy = LIST_FIRST(&priv->policies); + while (dpaa2_policy != NULL) { + if (dpaa2_policy->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return (struct rte_flow_meter_policy *)dpaa2_policy; + } + dpaa2_policy = LIST_NEXT(dpaa2_policy, next); + } + rte_spinlock_unlock(&priv->meter_lock); + + return NULL; +} + +static int +dpaa2_mtr_profile_delete(struct rte_eth_dev *dev, + uint32_t profile_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *dpaa2_profile = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->profiles); + while (curr != NULL) { + if (curr->profile_id == profile_id) { + dpaa2_profile = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_profile == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->profile_id == profile_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, + &profile_id, "Meter profile is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_profile, next); + rte_free(dpaa2_profile); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_policy_delete(struct rte_eth_dev *dev, + uint32_t policy_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *dpaa2_policy = NULL, *curr; + struct dpaa2_dev_meter *meter; + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->policies); + while (curr != NULL) { + if (curr->policy_id == policy_id) { + dpaa2_policy = curr; + break; + } + curr = LIST_NEXT(curr, next); + } + if (dpaa2_policy == NULL) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is invalid."); + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->policy_id == policy_id) { + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, EBUSY, + RTE_MTR_ERROR_TYPE_METER_POLICY_ID, + NULL, "Meter policy is in use."); + } + meter = LIST_NEXT(meter, next); + } + + LIST_REMOVE(dpaa2_policy, next); + rte_free(dpaa2_policy); + rte_spinlock_unlock(&priv->meter_lock); + + return 0; +} + +static int +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_params *params, + int shared, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter, *curr; + uint32_t profile_id, policy_id; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + RTE_SET_USED(shared); + + if (!(priv->options & DPNI_OPT_HAS_POLICING)) + return -rte_mtr_error_set(error, ENOTSUP, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, + "policing not enabled in DPNI"); + + /* mtr_id maps 1:1 to an Rx TC; validate the range. */ + if (mtr_id >= priv->num_rx_tc) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%u) >= num_rx_tc(%u)!", mtr_id, + priv->num_rx_tc); + return rte_mtr_error_set(error, EINVAL, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); + } + + profile_id = params->meter_profile_id; + policy_id = params->meter_policy_id; + + rte_spinlock_lock(&priv->meter_lock); + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter profile ID(%d) not exist!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter policy ID(%d) not exist!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) exist!", mtr_id); + ret = EEXIST; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + meter = LIST_NEXT(meter, next); + } + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); + if (meter == NULL) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter memory alloc failed!"); + ret = ENOMEM; + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; + goto quit; + } + meter->meter_id = mtr_id; + meter->profile_id = profile_id; + meter->policy_id = policy_id; + + rte_spinlock_unlock(&priv->meter_lock); + + /* Program the hardware policing configuration for this TC. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + rte_free(meter); + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW policing set failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + rte_spinlock_lock(&priv->meter_lock); + curr = LIST_FIRST(&priv->meters); + if (curr == NULL) { + LIST_INSERT_HEAD(&priv->meters, meter, next); + } else { + while (LIST_NEXT(curr, next) != NULL) + curr = LIST_NEXT(curr, next); + LIST_INSERT_AFTER(curr, meter, next); + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) { + if (meter != NULL && ret == ENOMEM) + rte_free(meter); + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + } + + return 0; +} + +static int +dpaa2_mtr_meter_destroy(struct rte_eth_dev *dev, + uint32_t mtr_id, struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_priv *priv_dev = dev->data->dev_private; + struct fsl_mc_io *dpni = priv_dev->hw; + struct dpaa2_dev_meter *meter; + struct dpni_rx_tc_policing_cfg cfg; + int ret; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + LIST_REMOVE(meter, next); + rte_free(meter); + rte_spinlock_unlock(&priv->meter_lock); + + /* Disable policing for this TC. */ + memset(&cfg, 0, sizeof(cfg)); + cfg.mode = DPNI_POLICER_MODE_NONE; + ret = dpni_set_rx_tc_policing(dpni, CMD_PRI_LOW, + priv->token, + (uint8_t)mtr_id, &cfg); + if (ret) + DPAA2_PMD_ERR("TC[%u] policing disable failed (%d)", + mtr_id, ret); + + return 0; + } + meter = LIST_NEXT(meter, next); + } + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) does not exist!", mtr_id); + rte_spinlock_unlock(&priv->meter_lock); + return rte_mtr_error_set(error, ENOENT, + RTE_MTR_ERROR_TYPE_MTR_ID, NULL, s_err_msg); +} + +static int +dpaa2_mtr_meter_profile_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t profile_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Profile ID(%d) not found!", profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + + /* Find the current policy so we can reprogram HW. */ + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == meter->policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current policy ID(%d) not found!", meter->policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new profile. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + /* Commit the new profile id only after HW succeeded. */ + meter->profile_id = profile_id; + + return 0; +} + +static int +dpaa2_mtr_meter_policy_update(struct rte_eth_dev *dev, + uint32_t mtr_id, uint32_t policy_id, + struct rte_mtr_error *error) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter_policy *policy; + struct dpaa2_dev_meter_profile *profile; + struct dpaa2_dev_meter *meter; + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; + bool found = false; + int ret = 0; + + rte_spinlock_lock(&priv->meter_lock); + meter = LIST_FIRST(&priv->meters); + while (meter != NULL) { + if (meter->meter_id == mtr_id) { + found = true; + break; + } + meter = LIST_NEXT(meter, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Meter ID(%d) not found!", mtr_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; + goto quit; + } + + found = false; + policy = LIST_FIRST(&priv->policies); + while (policy != NULL) { + if (policy->policy_id == policy_id) { + found = true; + break; + } + policy = LIST_NEXT(policy, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Policy ID(%d) not found!", policy_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; + goto quit; + } + + /* Find the current profile so we can reprogram HW. */ + found = false; + profile = LIST_FIRST(&priv->profiles); + while (profile != NULL) { + if (profile->profile_id == meter->profile_id) { + found = true; + break; + } + profile = LIST_NEXT(profile, next); + } + if (!found) { + snprintf(s_err_msg, sizeof(s_err_msg), + "Current profile ID(%d) not found!", meter->profile_id); + ret = ENOENT; + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; + goto quit; + } + +quit: + rte_spinlock_unlock(&priv->meter_lock); + if (ret != 0) + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); + + /* Reprogram hardware with the new policy. */ + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); + if (ret) { + snprintf(s_err_msg, sizeof(s_err_msg), + "TC[%u] HW reprogram failed (%d)!", mtr_id, ret); + return rte_mtr_error_set(error, -ret, + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); + } + + /* Commit the new policy id only after HW succeeded. */ + meter->policy_id = policy_id; + + return 0; +} + +static const struct rte_mtr_ops dpaa2_meter_ops = { + .capabilities_get = dpaa2_mtr_capabilities_get, + .meter_profile_add = dpaa2_mtr_profile_add, + .meter_profile_delete = dpaa2_mtr_profile_delete, + .meter_policy_add = dpaa2_mtr_policy_add, + .meter_policy_delete = dpaa2_mtr_policy_delete, + .meter_profile_get = dpaa2_mtr_profile_get, + .meter_policy_get = dpaa2_mtr_policy_get, + .create = dpaa2_mtr_meter_create, + .destroy = dpaa2_mtr_meter_destroy, + .meter_profile_update = dpaa2_mtr_meter_profile_update, + .meter_policy_update = dpaa2_mtr_meter_policy_update, +}; + +void +dpaa2_mtr_deinit(struct rte_eth_dev *dev) +{ + struct dpaa2_dev_priv *priv = dev->data->dev_private; + struct dpaa2_dev_meter *m; + struct dpaa2_dev_meter_policy *p; + struct dpaa2_dev_meter_profile *pf; + + rte_spinlock_lock(&priv->meter_lock); + while ((m = LIST_FIRST(&priv->meters)) != NULL) { + LIST_REMOVE(m, next); + rte_free(m); + } + while ((p = LIST_FIRST(&priv->policies)) != NULL) { + LIST_REMOVE(p, next); + rte_free(p); + } + while ((pf = LIST_FIRST(&priv->profiles)) != NULL) { + LIST_REMOVE(pf, next); + rte_free(pf); + } + rte_spinlock_unlock(&priv->meter_lock); +} + +int +dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops) +{ + RTE_SET_USED(dev); + + *(const void **)ops = &dpaa2_meter_ops; + return 0; +} diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 8913b408e7..aff0deee08 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -1111,6 +1111,10 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, */ #define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 +/** + * Do NOT reset counters generally for policer update + */ + /** * enum dpni_policer_mode - selecting the policer mode * @DPNI_POLICER_MODE_NONE: Policer is disabled @@ -1127,12 +1131,17 @@ enum dpni_policer_mode { /** * enum dpni_policer_unit - DPNI policer units - * @DPNI_POLICER_UNIT_BYTES: bytes units + * @DPNI_POLICER_UNIT_BYTES_L3: bytes units (for each frame takes into account + * FD length - L3 offset) * @DPNI_POLICER_UNIT_FRAMES: frames units + * @DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS: bytes units (for each frame takes + * into account FD length - L2 offset, which means L2 size without the 4 bytes + * for the FCS) */ enum dpni_policer_unit { - DPNI_POLICER_UNIT_BYTES = 0, - DPNI_POLICER_UNIT_FRAMES + DPNI_POLICER_UNIT_BYTES_L3 = 0, + DPNI_POLICER_UNIT_FRAMES, + DPNI_POLICER_UNIT_BYTES_L2_WITHOUT_FCS, }; /** @@ -1173,13 +1182,13 @@ struct dpni_rx_tc_policing_cfg { uint32_t ebs; }; - int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, uint8_t tc_id, const struct dpni_rx_tc_policing_cfg *cfg); + int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token, diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..808dad8112 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -11,6 +11,7 @@ sources = files( 'base/dpaa2_hw_dpni.c', 'base/dpaa2_tlu_hash.c', 'dpaa2_tm.c', + 'dpaa2_meter.c', 'dpaa2_mux.c', 'dpaa2_ethdev.c', 'dpaa2_flow.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v9-S2 05/13] net/dpaa2: support meter and policing 2026-10-12 7:04 ` [PATCH v9-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-10-13 14:55 ` Stephen Hemminger 2026-10-13 14:56 ` Stephen Hemminger 2026-10-13 15:11 ` Stephen Hemminger 2 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-13 14:55 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, Gagandeep Singh On Mon, 12 Oct 2026 12:34:36 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > + * color_aware mode is not yet implemented: the firmware color input from > + * FD[DROPP] is not read or acted upon. Advertise only blind (non-aware) > + * trTCM variants until color-aware handling is added. > + */ > +static struct rte_mtr_capabilities s_dpaa2_mtr_capa = { > + .color_aware_trtcm_rfc2698_supported = false, > + .color_aware_trtcm_rfc4115_supported = false, > + .trtcm_rfc2698_byte_mode_supported = true, > + .trtcm_rfc2698_packet_mode_supported = true, > + .trtcm_rfc4115_byte_mode_supported = true, > + .trtcm_rfc4115_packet_mode_supported = true > +}; Can this be constant? ^ permalink raw reply [flat|nested] 356+ messages in thread
* Re: [PATCH v9-S2 05/13] net/dpaa2: support meter and policing 2026-10-12 7:04 ` [PATCH v9-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-10-13 14:55 ` Stephen Hemminger @ 2026-10-13 14:56 ` Stephen Hemminger 2026-10-13 15:11 ` Stephen Hemminger 2 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-13 14:56 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, Gagandeep Singh On Mon, 12 Oct 2026 12:34:36 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > + > + /* Check for duplicate ID and insert under lock to prevent TOCTOU. */ > + rte_spinlock_lock(&priv->meter_lock); > + curr = LIST_FIRST(&priv->profiles); > + while (curr != NULL) { > + if (curr->profile_id == profile_id) { > + rte_spinlock_unlock(&priv->meter_lock); > + rte_mtr_error_set(error, EEXIST, > + RTE_MTR_ERROR_TYPE_METER_PROFILE_ID, > + NULL, "Meter profile ID already exists!"); > + ret = -EEXIST; > + goto err; > + } > + curr = LIST_NEXT(curr, next); > + } You are just open coding LIST_FOREACH() and other places. Better to use the macro. ^ permalink raw reply [flat|nested] 356+ messages in thread
* Re: [PATCH v9-S2 05/13] net/dpaa2: support meter and policing 2026-10-12 7:04 ` [PATCH v9-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-10-13 14:55 ` Stephen Hemminger 2026-10-13 14:56 ` Stephen Hemminger @ 2026-10-13 15:11 ` Stephen Hemminger 2 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-13 15:11 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, Gagandeep Singh There is a race here. > static int > +dpaa2_mtr_meter_create(struct rte_eth_dev *dev, > + uint32_t mtr_id, struct rte_mtr_params *params, > + int shared, struct rte_mtr_error *error) > +{ > + struct dpaa2_dev_priv *priv = dev->data->dev_private; > + struct dpaa2_dev_meter_profile *profile; > + struct dpaa2_dev_meter_policy *policy; > + struct dpaa2_dev_meter *meter, *curr; > + uint32_t profile_id, policy_id; > + enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE; > + bool found = false; > + int ret = 0; > + ... > + rte_spinlock_lock(&priv->meter_lock); > + profile = LIST_FIRST(&priv->profiles); > + while (profile != NULL) { > + if (profile->profile_id == profile_id) { > + found = true; > + break; > + } > + profile = LIST_NEXT(profile, next); > + } > + if (!found) { > + snprintf(s_err_msg, sizeof(s_err_msg), > + "Meter profile ID(%d) not exist!", profile_id); > + ret = ENOENT; > + err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID; > + goto quit; > + } > + > + found = false; > + policy = LIST_FIRST(&priv->policies); > + while (policy != NULL) { > + if (policy->policy_id == policy_id) { > + found = true; > + break; > + } > + policy = LIST_NEXT(policy, next); > + } > + if (!found) { > + snprintf(s_err_msg, sizeof(s_err_msg), > + "Meter policy ID(%d) not exist!", policy_id); > + ret = ENOENT; > + err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID; > + goto quit; > + } > + meter = LIST_FIRST(&priv->meters); > + while (meter != NULL) { > + if (meter->meter_id == mtr_id) { > + snprintf(s_err_msg, sizeof(s_err_msg), > + "Meter ID(%d) exist!", mtr_id); > + ret = EEXIST; > + err_type = RTE_MTR_ERROR_TYPE_MTR_ID; > + goto quit; > + } > + meter = LIST_NEXT(meter, next); > + } > + meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0); > + if (meter == NULL) { > + snprintf(s_err_msg, sizeof(s_err_msg), > + "Meter memory alloc failed!"); > + ret = ENOMEM; > + err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED; > + goto quit; > + } > + meter->meter_id = mtr_id; > + meter->profile_id = profile_id; > + meter->policy_id = policy_id; > + > + rte_spinlock_unlock(&priv->meter_lock); At this point meter is created but not put into any list. > + > + /* Program the hardware policing configuration for this TC. */ > + ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy); > + if (ret) { > + rte_free(meter); > + snprintf(s_err_msg, sizeof(s_err_msg), > + "TC[%u] HW policing set failed (%d)!", mtr_id, ret); > + return rte_mtr_error_set(error, -ret, > + RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg); > + } > + > + rte_spinlock_lock(&priv->meter_lock); While HW was being programmed, in theory the policy and mtr_id could have gone away. Either refcount the mtr_id or do a quick rescan to make sure it hasn't disappeared. > + curr = LIST_FIRST(&priv->meters); > + if (curr == NULL) { > + LIST_INSERT_HEAD(&priv->meters, meter, next); > + } else { > + while (LIST_NEXT(curr, next) != NULL) > + curr = LIST_NEXT(curr, next); > + LIST_INSERT_AFTER(curr, meter, next); > + } > + > +quit: > + rte_spinlock_unlock(&priv->meter_lock); > + if (ret != 0) { > + if (meter != NULL && ret == ENOMEM) > + rte_free(meter); > + return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg); > + } > + > + return 0; > +} The code would also be easier to read with helper functions that looked up in list rather lots of open coded list walks. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v9-S2 06/13] net/dpaa2: support flow drop action 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (4 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta ` (8 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 07/13] net/dpaa2: set default flow miss action per device 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (5 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (7 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global defaulting to 0 and optionally overridden via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. Replace it with a per-device default_flow field in dpaa2_dev_priv, initialised to the lowest-priority flow ID (min(fs_entries, dist_queues) - 1) at probe time, so that each device has its own independent miss-flow setting. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 4522d988ad..5d20a96f1c 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -105,6 +105,10 @@ New Features * Added the inner IP header to the RSS hash so tunneled traffic is distributed across the Rx queues. * Added support for traffic metering and policing (rte_mtr API). + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id now defaults to the lowest-priority + flow of the device. Users who previously redirected unmatched frames + to a specific queue via this variable must use the rte_flow API instead. * **Updated NXP ENETC4 PMD.** diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 10f9a90639..9878e2b06f 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3541,6 +3541,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MAX(RTE_MIN(priv->fs_entries, + priv->dist_queues), 1) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); rte_spinlock_init(&priv->meter_lock); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 20817c6b37..2253a27a4b 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -436,6 +436,8 @@ struct dpaa2_dev_priv { uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; rte_spinlock_t meter_lock; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..03f9193f51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (6 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta ` (6 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are stored via rte_mbuf_sched_set() for use by the scheduler. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 20 +++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 2253a27a4b..ab5bcc34f0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 03f9193f51..b7b79929b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..62565486a7 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,23 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->ol_flags |= + RTE_MBUF_F_RX_FDIR | + RTE_MBUF_F_RX_FDIR_ID; + m->hash.fdir.hi = (tc << 16) | flow; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 09/13] net/dpaa2: add minimum key size support 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (7 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta ` (5 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Support for 24-byte QoS key entries is available from DPNI version 8.7 onwards. For older DPNI versions, the existing 56-byte entry size is retained to maintain compatibility. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b7b79929b4..61a080893d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4519,7 +4522,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4529,11 +4532,11 @@ dpaa2_flow_entry_size(uint16_t key_max_size) return 0; } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || + dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int @@ -4595,7 +4598,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4686,7 +4689,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4977,11 +4980,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 10/13] net/dpaa2: restructure dpaa2 parser processing 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (8 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (4 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Move parse-result decoding into dpaa2_parser_decode.h, shared between the flow code and the Rx path. IPV4/6_EXT, SCTP and ICMP ptypes are removed from the rx_parse_new fast-path switch and now go through dpaa2_dev_rx_parse_frc(). Also: - Wire parser result dumping to DPAA2_PRINT_RX_PARSER_RESULT. - Move parser decode helpers into dpaa2_parser_decode.h for reuse by flow and Rx paths. - Consolidate FLC RSS/FDIR handling in a common helper. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 2 +- drivers/net/dpaa2/dpaa2_ethdev.h | 176 ++- drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ drivers/net/dpaa2/dpaa2_parser_decode.h | 1551 +++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + drivers/net/dpaa2/dpaa2_rxtx.c | 344 +++-- 6 files changed, 1957 insertions(+), 557 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 9878e2b06f..88ff5daba4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3592,7 +3592,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (getenv("DPAA2_PRINT_RX_PARSER_RESULT")) - dpaa2_print_parser_result = 1; + priv->flags |= DPAA2_RX_PRINT_PSR_RESULT_FLAG; /* Allocate memory for hardware structure for queues */ ret = dpaa2_alloc_rx_tx_queues(eth_dev); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index ab5bcc34f0..acf377730a 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -21,6 +21,8 @@ #include <mc/fsl_dpmac.h> #include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_parser_decode.h" + #define DPAA2_MIN_RX_BUF_SIZE 512 #define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ @@ -101,6 +103,7 @@ #define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) #define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 @@ -124,31 +127,62 @@ RTE_ETH_RSS_PPPOE) /* LX2 FRC Parsed values (Little Endian) */ -#define DPAA2_PKT_TYPE_ETHER 0x0060 -#define DPAA2_PKT_TYPE_IPV4 0x0000 -#define DPAA2_PKT_TYPE_IPV6 0x0020 +#define DPAA2_PKT_TYPE_ETHER \ + (DPAA2_PSR_SUMMARY_NONIP << DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) +#define DPAA2_PKT_TYPE_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_BIT_SIZE) + +/**Tunnel*/ +#define DPAA2_PKT_TYPE_L3_EXT \ + (DPAA2_PSR_SUMMARY_L4_EXT << DPAA2_PSR_SUMMARY_L4_EXT_L3_POS) +#define DPAA2_PKT_TYPE_L3_EXT_IPV4 \ + (DPAA2_PSR_SUMMARY_IPV4 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) +#define DPAA2_PKT_TYPE_L3_EXT_IPV6 \ + (DPAA2_PSR_SUMMARY_IPV6 << DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE) #define DPAA2_PKT_TYPE_IPV4_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ - (0x0001 | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PKT_TYPE_L3_EXT | DPAA2_PKT_TYPE_L3_EXT_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV4_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV4_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6 \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6) +#define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ + (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + #define DPAA2_PKT_TYPE_IPV4_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ - (0x000e | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV4) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_UDP \ - (0x0010 | DPAA2_PKT_TYPE_IPV6) -#define DPAA2_PKT_TYPE_IPV4_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_SCTP \ - (0x000f | DPAA2_PKT_TYPE_IPV6) + (DPAA2_PSR_SUMMARY_UDP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_SCTP \ + (DPAA2_PSR_SUMMARY_SCTP | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) -#define DPAA2_PKT_TYPE_VLAN_1 0x0160 -#define DPAA2_PKT_TYPE_VLAN_2 0x0260 + (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) + +#define DPAA2_PKT_TYPE_VLAN_1 0x0100 +#define DPAA2_PKT_TYPE_VLAN_2 0x0200 +#define DPAA2_PKT_TYPE_VLAN \ + (DPAA2_PKT_TYPE_VLAN_1 | DPAA2_PKT_TYPE_VLAN_2) /* mac counters */ #define DPAA2_MAC_NUM_STATS (DPMAC_CNT_EGR_CONTROL_FRAME + 1) @@ -173,18 +207,40 @@ struct sw_buf_free { struct rte_mbuf *seg; }; -/* enable timestamp in mbuf*/ -extern bool dpaa2_enable_ts[]; -extern uint64_t dpaa2_timestamp_rx_dynflag; -extern int dpaa2_timestamp_dynfield_offset; - /* Externally defined */ extern const struct rte_flow_ops dpaa2_flow_ops; extern const struct rte_tm_ops dpaa2_tm_ops; +extern bool dpaa2_enable_ts[]; +extern uint64_t dpaa2_timestamp_rx_dynflag; +extern int dpaa2_timestamp_dynfield_offset; + extern bool dpaa2_print_parser_result; +struct dpaa2_dyn_rx_protocol_pos { + uint8_t l3_offset; + uint8_t l4_offset; + uint8_t l5_offset; + uint8_t rsv; +}; + +#define L3_OFFSET_OF_MBUF_DYN 0 +#define L4_OFFSET_OF_MBUF_DYN 1 +#define L5_OFFSET_OF_MBUF_DYN 2 + +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_FAPR_SIZE \ (sizeof(struct dpaa2_annot_hdr) - \ offsetof(struct dpaa2_annot_hdr, word3)) @@ -258,42 +314,6 @@ enum dpaa2_ecpri_fafe_type { #define DPAA2_PR_L5_OFF_OFFSET 31 #define DPAA2_PR_NXTHDR_OFF_OFFSET 34 -/* Set by SP for vxlan distribution start*/ -#define DPAA2_VXLAN_IN_TCI_OFFSET 16 - -#define DPAA2_VXLAN_IN_DADDR0_OFFSET 20 -#define DPAA2_VXLAN_IN_DADDR1_OFFSET 22 -#define DPAA2_VXLAN_IN_DADDR2_OFFSET 24 -#define DPAA2_VXLAN_IN_DADDR3_OFFSET 25 -#define DPAA2_VXLAN_IN_DADDR4_OFFSET 26 -#define DPAA2_VXLAN_IN_DADDR5_OFFSET 28 - -#define DPAA2_VXLAN_IN_SADDR0_OFFSET 29 -#define DPAA2_VXLAN_IN_SADDR1_OFFSET 32 -#define DPAA2_VXLAN_IN_SADDR2_OFFSET 33 -#define DPAA2_VXLAN_IN_SADDR3_OFFSET 35 -#define DPAA2_VXLAN_IN_SADDR4_OFFSET 41 -#define DPAA2_VXLAN_IN_SADDR5_OFFSET 42 - -#define DPAA2_VXLAN_VNI_OFFSET 43 -#define DPAA2_VXLAN_IN_TYPE_OFFSET 46 -/* Set by SP for vxlan distribution end*/ - -/* ECPRI shares SP context with VXLAN*/ -#define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET - -#define DPAA2_FS_FLC_FS_MARK_OFFSET \ - (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_OFFSET \ - (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) - -#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) -#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) - -#define DPAA2_FS_FLC_FLOW_OFFSET \ - (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) - #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { @@ -435,6 +455,7 @@ struct dpaa2_dev_priv { void *tx_conf_vq[MAX_TX_QUEUES * DPAA2_MAX_CHANNELS]; void *rx_err_vq; uint32_t flags; /*dpaa2 config flags */ + int psr_dynfield_offset; uint8_t max_mac_filters; uint8_t max_vlan_filters; uint8_t num_rx_tc; @@ -474,6 +495,9 @@ struct dpaa2_dev_priv { uint64_t rx_timestamp; /*stores timestamp of last received tx confirmation packet on dev*/ uint64_t tx_timestamp; + + int rx_ts_offset; + uint64_t rx_ts_flag; /* stores pointer to next tx_conf queue that should be processed, * it corresponds to last packet transmitted */ @@ -482,6 +506,7 @@ struct dpaa2_dev_priv { struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */ rte_spinlock_t lpbk_qp_lock; + bool sp_protocol; uint8_t channel_inuse; /* Rx-interrupt mode latched at the first dev_configure */ uint8_t intr_mode; @@ -513,6 +538,41 @@ static inline int dpaa2_dev_cmp_dpni_ver(struct dpaa2_dev_priv *priv, return priv->dpni_ver_major - ver_major; } +static inline void +dpaa2_dev_rx_print_parser_result(struct dpaa2_dev_priv *priv, + const struct qbman_fd *fd, const struct rte_mbuf *m) +{ + size_t fd_addr; + void *hw_annot_addr; + + if (likely(!(priv->flags & DPAA2_RX_PRINT_PSR_RESULT_FLAG))) + return; + + if (dpaa2_svr_family == SVR_LX2160A) + dpaa2_print_fd_frc(fd); + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + dpaa2_print_parse_result(hw_annot_addr, priv->sp_protocol); + if (m->ol_flags & RTE_MBUF_F_RX_FDIR) { + const struct rte_mbuf_sched *sched; + uint16_t i; + struct dpaa2_queue *rxq; + + sched = &m->hash.sched; + for (i = 0; i < MAX_RX_QUEUES; i++) { + rxq = priv->rx_vq[i]; + if (rxq->tc_index == sched->traffic_class && + rxq->flow_id == sched->queue_id) + break; + } + DPAA2_PMD_DEBUG("Directed to TC%d-flow%d(rxq%d), color(%d)", + sched->traffic_class, sched->queue_id, i, sched->color); + } else if (m->ol_flags & RTE_MBUF_F_RX_RSS_HASH) { + DPAA2_PMD_DEBUG("Balanced with hash(0x%08x)", m->hash.rss); + } +} + int dpaa2_distset_to_dpkg_profile_cfg(uint64_t req_dist_set, struct dpkg_profile_cfg *kg_cfg); diff --git a/drivers/net/dpaa2/dpaa2_parse_dump.h b/drivers/net/dpaa2/dpaa2_parse_dump.h deleted file mode 100644 index bcab3bf0cb..0000000000 --- a/drivers/net/dpaa2/dpaa2_parse_dump.h +++ /dev/null @@ -1,374 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2022 NXP - * - */ - -#ifndef _DPAA2_PARSE_DUMP_H -#define _DPAA2_PARSE_DUMP_H - -#include <rte_event_eth_rx_adapter.h> -#include <rte_pmd_dpaa2.h> - -#include <dpaa2_hw_pvt.h> -#include "dpaa2_tm.h" - -#include <mc/fsl_dpni.h> -#include <mc/fsl_mc_sys.h> - -#include "base/dpaa2_hw_dpni_annot.h" - -#define DPAA2_PR_PRINT printf - -struct dpaa2_faf_bit_info { - const char *name; - int position; -}; - -struct dpaa2_fapr_field_info { - const char *name; - uint16_t value; -}; - -struct dpaa2_fapr_array { - union { - uint64_t pr_64[DPAA2_FAPR_SIZE / 8]; - uint8_t pr[DPAA2_FAPR_SIZE]; - }; -}; - -#define NEXT_HEADER_NAME "Next Header" -#define ETH_OFF_NAME "ETH OFFSET" -#define VLAN_TCI_OFF_NAME "VLAN TCI OFFSET" -#define LAST_ENTRY_OFF_NAME "LAST ETYPE Offset" -#define L3_OFF_NAME "L3 Offset" -#define L4_OFF_NAME "L4 Offset" -#define L5_OFF_NAME "L5 Offset" -#define NEXT_HEADER_OFF_NAME "Next Header Offset" - -static const -struct dpaa2_fapr_field_info support_dump_fields[] = { - { - .name = NEXT_HEADER_NAME, - }, - { - .name = ETH_OFF_NAME, - }, - { - .name = VLAN_TCI_OFF_NAME, - }, - { - .name = LAST_ENTRY_OFF_NAME, - }, - { - .name = L3_OFF_NAME, - }, - { - .name = L4_OFF_NAME, - }, - { - .name = L5_OFF_NAME, - }, - { - .name = NEXT_HEADER_OFF_NAME, - } -}; - -static inline void -dpaa2_print_ecpri(struct dpaa2_fapr_array *fapr) -{ - uint8_t ecpri_type; - struct rte_ecpri_combined_msg_hdr ecpri_msg; - - ecpri_type = fapr->pr[DPAA2_FAFE_PSR_OFFSET]; - if ((ecpri_type >> 1) > 7) { - DPAA2_PR_PRINT("Invalid ECPRI type(0x%02x)\r\n", - ecpri_type); - } else { - DPAA2_PR_PRINT("ECPRI type %d present\r\n", - ecpri_type >> 1); - if (ecpri_type == ECPRI_FAFE_TYPE_0 || - ecpri_type == ECPRI_FAFE_TYPE_1) { - /* Type 0 is identical to type1*/ - ecpri_msg.type0.pc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type0.pc_id = - ecpri_msg.type0.pc_id << 8; - ecpri_msg.type0.pc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type0.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type0.seq_id = - ecpri_msg.type0.seq_id << 8; - ecpri_msg.type0.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type0.pc_id), - rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_2) { - ecpri_msg.type2.rtc_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type2.rtc_id = - ecpri_msg.type2.rtc_id << 8; - ecpri_msg.type2.rtc_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type2.seq_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type2.seq_id = - ecpri_msg.type2.seq_id << 8; - ecpri_msg.type2.seq_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), - rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_3) { - DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); - } else if (ecpri_type == ECPRI_FAFE_TYPE_4) { - ecpri_msg.type4.rma_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type4.rw = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] >> 4; - ecpri_msg.type4.rr = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1] & 0xf; - - ecpri_msg.type4.ele_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - ecpri_msg.type4.ele_id = - ecpri_msg.type4.ele_id << 8; - ecpri_msg.type4.ele_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", - ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); - DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", - ecpri_msg.type4.rr, - rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); - } else if (ecpri_type == ECPRI_FAFE_TYPE_5) { - ecpri_msg.type5.msr_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type5.act_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - - DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", - ecpri_msg.type5.msr_id, - ecpri_msg.type5.act_type); - } else if (ecpri_type == ECPRI_FAFE_TYPE_6) { - ecpri_msg.type6.rst_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type6.rst_id = - ecpri_msg.type6.rst_id << 8; - ecpri_msg.type6.rst_id |= - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - - ecpri_msg.type6.rst_op = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - - DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", - rte_be_to_cpu_16(ecpri_msg.type6.rst_id), - ecpri_msg.type6.rst_op); - } else if (ecpri_type == ECPRI_FAFE_TYPE_7) { - ecpri_msg.type7.evt_id = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET]; - ecpri_msg.type7.evt_type = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 1]; - ecpri_msg.type7.seq = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 2]; - ecpri_msg.type7.number = - fapr->pr[DPAA2_ECPRI_MSG_OFFSET + 3]; - - DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", - ecpri_msg.type7.evt_id, - ecpri_msg.type7.evt_type); - DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", - ecpri_msg.type7.seq, - ecpri_msg.type7.number); - } - } -} - -static inline void -dpaa2_print_faf(struct dpaa2_fapr_array *fapr) -{ - const int faf_bit_len = DPAA2_FAF_TOTAL_SIZE * 8; - struct dpaa2_faf_bit_info faf_bits[faf_bit_len]; - int i, byte_pos, bit_pos, vxlan = 0, vxlan_vlan = 0; - struct rte_ether_hdr vxlan_in_eth; - uint16_t vxlan_vlan_tci; - int ecpri = 0; - - for (i = 0; i < faf_bit_len; i++) { - faf_bits[i].position = i; - if (i == FAFE_VXLAN_IN_VLAN_FRAM) - faf_bits[i].name = "VXLAN VLAN Present"; - else if (i == FAFE_VXLAN_IN_IPV4_FRAM) - faf_bits[i].name = "VXLAN IPV4 Present"; - else if (i == FAFE_VXLAN_IN_IPV6_FRAM) - faf_bits[i].name = "VXLAN IPV6 Present"; - else if (i == FAFE_VXLAN_IN_UDP_FRAM) - faf_bits[i].name = "VXLAN UDP Present"; - else if (i == FAFE_VXLAN_IN_TCP_FRAM) - faf_bits[i].name = "VXLAN TCP Present"; - else if (i == FAF_VXLAN_FRAM) - faf_bits[i].name = "VXLAN Present"; - else if (i == FAF_ETH_FRAM) - faf_bits[i].name = "Ethernet MAC Present"; - else if (i == FAF_VLAN_FRAM) - faf_bits[i].name = "VLAN 1 Present"; - else if (i == FAF_IPV4_FRAM) - faf_bits[i].name = "IPv4 1 Present"; - else if (i == FAF_IPV6_FRAM) - faf_bits[i].name = "IPv6 1 Present"; - else if (i == FAF_IP_FRAG_FRAM) - faf_bits[i].name = "IP fragment Present"; - else if (i == FAF_UDP_FRAM) - faf_bits[i].name = "UDP Present"; - else if (i == FAF_TCP_FRAM) - faf_bits[i].name = "TCP Present"; - else if (i == FAFE_ECPRI_FRAM) - faf_bits[i].name = "ECPRI Present"; - else - faf_bits[i].name = "Check RM for this unusual frame"; - } - - DPAA2_PR_PRINT("Frame Annotation Flags:\r\n"); - for (i = 0; i < faf_bit_len; i++) { - byte_pos = i / 8 + DPAA2_FAFE_PSR_OFFSET; - bit_pos = i % 8; - if (fapr->pr[byte_pos] & (1 << (7 - bit_pos))) { - DPAA2_PR_PRINT("FAF bit %d : %s\r\n", - faf_bits[i].position, faf_bits[i].name); - if (i == FAF_VXLAN_FRAM) - vxlan = 1; - else if (i == FAFE_ECPRI_FRAM) - ecpri = 1; - } - } - - if (vxlan) { - vxlan_in_eth.dst_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_DADDR0_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_DADDR1_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_DADDR2_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_DADDR3_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_DADDR4_OFFSET]; - vxlan_in_eth.dst_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_DADDR5_OFFSET]; - - vxlan_in_eth.src_addr.addr_bytes[0] = - fapr->pr[DPAA2_VXLAN_IN_SADDR0_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[1] = - fapr->pr[DPAA2_VXLAN_IN_SADDR1_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[2] = - fapr->pr[DPAA2_VXLAN_IN_SADDR2_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[3] = - fapr->pr[DPAA2_VXLAN_IN_SADDR3_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[4] = - fapr->pr[DPAA2_VXLAN_IN_SADDR4_OFFSET]; - vxlan_in_eth.src_addr.addr_bytes[5] = - fapr->pr[DPAA2_VXLAN_IN_SADDR5_OFFSET]; - - vxlan_in_eth.ether_type = - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET]; - vxlan_in_eth.ether_type = - vxlan_in_eth.ether_type << 8; - vxlan_in_eth.ether_type |= - fapr->pr[DPAA2_VXLAN_IN_TYPE_OFFSET + 1]; - - if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) - vxlan_vlan = 1; - DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); - DPAA2_PR_PRINT("dst addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.dst_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("src addr: "); - for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { - if (i != 0) - DPAA2_PR_PRINT(":"); - DPAA2_PR_PRINT("%02x", - vxlan_in_eth.src_addr.addr_bytes[i]); - } - DPAA2_PR_PRINT("\r\n"); - DPAA2_PR_PRINT("type: 0x%04x\r\n", - vxlan_in_eth.ether_type); - if (vxlan_vlan) { - vxlan_vlan_tci = fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET]; - vxlan_vlan_tci = vxlan_vlan_tci << 8; - vxlan_vlan_tci |= - fapr->pr[DPAA2_VXLAN_IN_TCI_OFFSET + 1]; - - DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", - vxlan_vlan_tci); - } - } - - if (ecpri) - dpaa2_print_ecpri(fapr); -} - -static inline void -dpaa2_print_parse_result(struct dpaa2_annot_hdr *annotation) -{ - struct dpaa2_fapr_array fapr; - struct dpaa2_fapr_field_info - fapr_fields[sizeof(support_dump_fields) / - sizeof(struct dpaa2_fapr_field_info)]; - uint64_t len, i; - - memcpy(&fapr, &annotation->word3, DPAA2_FAPR_SIZE); - for (i = 0; i < (DPAA2_FAPR_SIZE / 8); i++) - fapr.pr_64[i] = rte_cpu_to_be_64(fapr.pr_64[i]); - - memcpy(fapr_fields, support_dump_fields, - sizeof(support_dump_fields)); - - for (i = 0; - i < sizeof(fapr_fields) / - sizeof(struct dpaa2_fapr_field_info); - i++) { - if (!strcmp(fapr_fields[i].name, NEXT_HEADER_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_NXTHDR_OFFSET]; - fapr_fields[i].value = fapr_fields[i].value << 8; - fapr_fields[i].value |= - fapr.pr[DPAA2_PR_NXTHDR_OFFSET + 1]; - } else if (!strcmp(fapr_fields[i].name, ETH_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_ETH_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, VLAN_TCI_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_TCI_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, LAST_ENTRY_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_LAST_ETYPE_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L3_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L3_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L4_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L4_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, L5_OFF_NAME)) { - fapr_fields[i].value = fapr.pr[DPAA2_PR_L5_OFF_OFFSET]; - } else if (!strcmp(fapr_fields[i].name, NEXT_HEADER_OFF_NAME)) { - fapr_fields[i].value = - fapr.pr[DPAA2_PR_NXTHDR_OFF_OFFSET]; - } - } - - len = sizeof(fapr_fields) / sizeof(struct dpaa2_fapr_field_info); - DPAA2_PR_PRINT("Parse Result:\r\n"); - for (i = 0; i < len; i++) { - DPAA2_PR_PRINT("%21s : 0x%02x\r\n", - fapr_fields[i].name, fapr_fields[i].value); - } - dpaa2_print_faf(&fapr); -} - -#endif diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h new file mode 100644 index 0000000000..c57f08ae8c --- /dev/null +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -0,0 +1,1551 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2022-2026 NXP + * + */ + +#ifndef _DPAA2_PARSE_DECODE_H +#define _DPAA2_PARSE_DECODE_H + +#include <rte_flow.h> +#include <rte_event_eth_rx_adapter.h> +#include <rte_pmd_dpaa2.h> + +#include <bus_fslmc_driver.h> +#include <dpaa2_hw_pvt.h> +#include "dpaa2_tm.h" + +#include <mc/fsl_dpni.h> +#include <mc/fsl_mc_sys.h> + +#include "base/dpaa2_hw_dpni_annot.h" +#include "dpaa2_pmd_logs.h" + +#define DPAA2_PR_PRINT dpaa2_dump_print + +#define BIT_SIZE(t) (sizeof(t) * 8) +#define BIT_OFFSET(t, m) (offsetof(t, m) * 8) +#define BIT_LAST_OFFSET(t) (BIT_SIZE(t) - 1) + +#define ROCEV2_DEST_QP_SIZE 3 + +enum dpaa2_parser_protocol_id { + DPAA2_PARSER_MAC_ID, + DPAA2_PARSER_VLAN_ID, + DPAA2_PARSER_ICMP_ID, + DPAA2_PARSER_IP_ID, + DPAA2_PARSER_IPV4_ID, + DPAA2_PARSER_IPV6_ID, + DPAA2_PARSER_IP_FRAG_ID, + DPAA2_PARSER_GRE_ID, + DPAA2_PARSER_UDP_ID, + DPAA2_PARSER_TCP_ID, + DPAA2_PARSER_SCTP_ID, + DPAA2_PARSER_GTP_ID, + DPAA2_PARSER_IPSEC_AH_ID, + DPAA2_PARSER_IPSEC_ESP_ID, + DPAA2_PARSER_VXLAN_ID, + DPAA2_PARSER_TUNNEL_VLAN_ID, + DPAA2_PARSER_TUNNEL_IPV4_ID, + DPAA2_PARSER_TUNNEL_IPV6_ID, + DPAA2_PARSER_TUNNEL_UDP_ID, + DPAA2_PARSER_TUNNEL_TCP_ID, + DPAA2_PARSER_ECPRI_ID, + DPAA2_PARSER_ROCEV2_ID, + DPAA2_PARSER_GENEVE_ID +}; + +#define DPAA2_PSR_SUMMARY_NONIP 6 +#define DPAA2_PSR_SUMMARY_ARP 3 +#define DPAA2_PSR_SUMMARY_NONIP_PTP 4 +#define DPAA2_PSR_SUMMARY_MPLS 6 + +#define DPAA2_PSR_SUMMARY_L4_EXT 2 +#define DPAA2_PSR_SUMMARY_IPV4 0 +#define DPAA2_PSR_SUMMARY_IPV6 1 + +#define DPAA2_PSR_SUMMARY_GRE_IPV4 0 +#define DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP 1 +#define DPAA2_PSR_SUMMARY_GRE_IPV6 2 +#define DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP 3 + +#define DPAA2_PSR_SUMMARY_IP_FRAG 1 +#define DPAA2_PSR_SUMMARY_ICMP 3 +#define DPAA2_PSR_SUMMARY_IPSEC_ESP 5 +#define DPAA2_PSR_SUMMARY_TCP 14 +#define DPAA2_PSR_SUMMARY_SCTP 15 +#define DPAA2_PSR_SUMMARY_UDP 16 +#define DPAA2_PSR_SUMMARY_PTP 18 +#define DPAA2_PSR_SUMMARY_UDP_ESP_IKE 19 +#define DPAA2_PSR_SUMMARY_GTPU 20 +#define DPAA2_PSR_SUMMARY_GTPC 21 +#define DPAA2_PSR_SUMMARY_VXLAN 27 + +#define DPAA2_PSR_SUMMARY_L4_BIT_SIZE 5 +#define DPAA2_PSR_SUMMARY_L3_BIT_SIZE 2 + +#define DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE 1 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE 2 +#define DPAA2_PSR_SUMMARY_L4_EXT_L3_POS \ + (DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE + \ + DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE) + +#define DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE 4 +#define DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE 3 + +union __rte_packed_begin dpaa2_psr_summary_l { + struct { + uint8_t l4:DPAA2_PSR_SUMMARY_L4_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4; + struct { + uint8_t l4_ext:DPAA2_PSR_SUMMARY_L4_EXT_BIT_SIZE; + uint8_t ip:DPAA2_PSR_SUMMARY_L4_EXT_IP_BIT_SIZE; + uint8_t l3:DPAA2_PSR_SUMMARY_L4_EXT_L3_BIT_SIZE; + uint8_t fafe3:1; + } l4_ext; + struct { + uint8_t l2:DPAA2_PSR_SUMMARY_NON_IP_L2_BIT_SIZE; + uint8_t non_ip:DPAA2_PSR_SUMMARY_NON_IP_NON_IP_BIT_SIZE; + uint8_t fafe3:1; + } non_ip; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_psr_summary { + union dpaa2_psr_summary_l sum_l; + uint8_t vlan:2; + uint8_t l2_l2_ext:2; + uint8_t fafe2:1; + uint8_t fafe1:1; + uint8_t fafe0:1; + uint8_t checksum_err:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_psr_sum_16b { + uint16_t sum_16b; + struct dpaa2_psr_summary sum; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ingress_frc { + uint32_t rsv0:10; + + uint32_t faicfdv:1; + uint32_t faswov:1; + uint32_t faiadv:1; + uint32_t faprv:1; + uint32_t faeadv:1; + uint32_t fasv:1; + union dpaa2_psr_sum_16b psr_sum; +} __rte_packed_end; + +/* Frame annotation status */ +struct __rte_packed_begin dpaa2_fas_parse { + uint32_t status:8; + uint32_t ppid:6; + uint32_t rsv4:2; + uint32_t ifpid:12; + uint32_t rsv3:4; + uint32_t l4ce:1; + uint32_t l4cv:1; + uint32_t l3ce:1; + uint32_t l3cv:1; + uint32_t ble:1; + uint32_t phe:1; + uint32_t isp:1; + uint32_t pte:1; + uint32_t rsv2:4; + uint32_t fpe:1; + uint32_t fle:1; + uint32_t piee:1; + uint32_t tide:1; + uint32_t mnle:1; + uint32_t eofhe:1; + uint32_t kse:1; + uint32_t rsv1:6; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t ptp:1; + uint32_t rsv0:2; + uint32_t macsec:1; + uint32_t discard:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_fas_parse_32b { + uint32_t fas_32b; + struct dpaa2_fas_parse fas; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_ecpri { + uint8_t msg_type:5; + uint8_t non_used:2; + uint8_t ecpri:1; /**Always 1, FRC FAFE0*/ +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_fafe_rocev2_tunnel { + uint8_t in_vlan:1; + uint8_t in_udp:1; + uint8_t in_tcp:1; + uint8_t in_ipv6:1; + uint8_t in_ipv4:1; /**FRC FAFE3*/ + uint8_t geneve:1; /**FRC FAFE2*/ + uint8_t rocev2:1; /**FRC FAFE1*/ + uint8_t non_used:1; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_fafe_parse { + struct dpaa2_sp_fafe_ecpri ecpri; + struct dpaa2_sp_fafe_rocev2_tunnel rocev2_tunnel; + uint8_t fafe_8b; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse { + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_l_parse_be { + uint32_t ike:1; + uint32_t eth_slow:1; + uint32_t vxlan_err:1; + uint32_t vxlan:1; + uint32_t ptp:1; + uint32_t vlan_prio:1; + uint32_t gtp_prim:1; + uint32_t i6_r_hdr2:1; + + uint32_t fcoe:1; + uint32_t bpdu:1; + uint32_t broadcast:1; + uint32_t multicast:1; + uint32_t unicast:1; + uint32_t mac:1; + uint32_t psr_err:1; + uint32_t spsr_err:1; + + uint32_t gre_eth:1; + uint32_t vlan_n:1; + uint32_t vlan_1:1; + uint32_t llc_snap_err:1; + uint32_t unknown_llc_oui:1; + uint32_t llc_snap:1; + uint32_t eth_err:1; + uint32_t fip:1; + + uint32_t arp_err:1; + uint32_t arp:1; + uint32_t mpls_err:1; + uint32_t mpls_n:1; + uint32_t mpls_1:1; + uint32_t pppoe_ppp_err:1; + uint32_t pppoe_ppp:1; + uint32_t vlan_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse { + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_faf_h_parse_be { + uint32_t ipv4_n_unicast:1; + uint32_t ipv4_n:1; + uint32_t ipv4_1_broadcast:1; + uint32_t ipv4_1_multicast:1; + uint32_t ipv4_1_unicast:1; + uint32_t ipv4_1:1; + uint32_t l2_spsr_err:1; + uint32_t l2_unknown:1; + + uint32_t ipv6_n_multicast:1; + uint32_t ipv6_n_unicast:1; + uint32_t ipv6_n:1; + uint32_t ipv6_1_multicast:1; + uint32_t ipv6_1_unicast:1; + uint32_t ipv6_1:1; + uint32_t ipv4_n_broadcast:1; + uint32_t ipv4_n_multicast:1; + + uint32_t ip_n_frag:1; + uint32_t ip_n_unknown:1; + uint32_t ip_n_opt:1; + uint32_t ip_1_err:1; + uint32_t ip_1_init_frag:1; + uint32_t ip_1_frag:1; + uint32_t ip_1_unknown:1; + uint32_t ip_1_opt:1; + + uint32_t min_encp_s:1; + uint32_t min_encp:1; + uint32_t ip_n_err:1; + uint32_t udp_light:1; + uint32_t icmp_v6:1; + uint32_t igmp:1; + uint32_t icmp:1; + uint32_t ip_n_init_frag:1; + + uint32_t udp_err:1; + uint32_t udp:1; + uint32_t l3_spsr_err:1; + uint32_t l3_unknown:1; + uint32_t gre_err:1; + uint32_t gre_k:1; + uint32_t gre:1; + uint32_t min_encp_err:1; + + uint32_t ipsec_ah:1; + uint32_t ipsec_esp:1; + uint32_t ipsec:1; + uint32_t tcp_err:1; + uint32_t tcp_3_5:1; + uint32_t tcp_6_11:1; + uint32_t tcp_opt:1; + uint32_t tcp:1; + + uint32_t gtp:1; + uint32_t l4_spsr_err:1; + uint32_t l4_unknown:1; + uint32_t dccp_err:1; + uint32_t dccp:1; + uint32_t sctp_err:1; + uint32_t sctp:1; + uint32_t ipsec_err:1; + + uint32_t i6_r_hdr1:1; + uint32_t l5_spsr:1; + uint32_t capwap_data:1; + uint32_t capwap_ctl:1; + uint32_t iscsi:1; + uint32_t esp_err:1; + uint32_t esp:1; + uint32_t gtp_err:1; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_annot_word3_parse { + struct dpaa2_faf_l_parse faf_l; + uint8_t rsv; + union dpaa2_sp_fafe_parse fafe; + rte_be16_t nxthdr; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_ecpri_msg_rm_access { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ele_id:16; /**< Element ID */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rma_id:8; /**< Remote Memory Access ID */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t rma_id:8; /**< Remote Memory Access ID */ + uint32_t rw:4; /**< Read/Write */ + uint32_t rr:4; /**< Req/Resp */ + uint32_t ele_id:16; /**< Element ID */ +#endif +} __rte_packed_end; + +union __rte_packed_begin dpaa2_sp_ecpri_msg { + struct rte_ecpri_msg_iq_data type0; + struct rte_ecpri_msg_bit_seq type1; + struct rte_ecpri_msg_rtc_ctrl type2; + struct rte_ecpri_msg_bit_seq type3; + struct dpaa2_ecpri_msg_rm_access type4; + struct rte_ecpri_msg_delay_measure type5; + struct rte_ecpri_msg_remote_reset type6; + struct rte_ecpri_msg_event_ind type7; +} __rte_packed_end; + +#define DPAA2_SP_PSR_CTX_LEN 5 + +struct __rte_packed_begin dpaa2_sp_rocev2 { + uint8_t opcode; + uint8_t dest_qp[ROCEV2_DEST_QP_SIZE]; +} __rte_packed_end; + +struct __rte_packed_begin dpaa2_sp_geneve { + rte_be16_t protocol; + uint8_t geneve_vni[3]; +} __rte_packed_end; + +struct dpaa2_psr_result_word3 { + rte_be16_t nxthdr; + union dpaa2_sp_fafe_parse fafe; + uint8_t rsv; + struct dpaa2_faf_l_parse_be faf_l_be; +}; + +struct dpaa2_psr_result_word4 { + struct dpaa2_faf_h_parse_be faf_h_be; +}; + +struct dpaa2_psr_result_word5 { + union { + struct { + uint8_t shim_off1; + uint8_t shim_off2; + }; + rte_be16_t vxlan_vlan_tci; + }; + uint8_t ip_1_pid_off; + uint8_t eth_off; + union { + uint8_t llc_snap_off; + uint8_t vxlan_in_daddr0; + }; + uint8_t vlan_tci_1_off; + union { + uint8_t vlan_tci_n_off; + uint8_t vxlan_in_daddr1; + }; + uint8_t last_etype_off; +}; + +struct dpaa2_psr_result_word6 { + union { + uint8_t pppoe_off; + uint8_t vxlan_in_daddr2; + }; + union { + uint8_t mpls_1_off; + uint8_t vxlan_in_daddr3; + }; + union { + uint8_t mpls_n_off; + uint8_t vxlan_in_daddr4; + }; + uint8_t l3_off; + union { + uint8_t ip_n_off; + uint8_t vxlan_in_daddr5; + }; + union { + uint8_t gre_off; + uint8_t vxlan_in_saddr0; + }; + uint8_t l4_off; + uint8_t l5_off; +}; + +struct dpaa2_psr_result_word7 { + union { + uint8_t route_hdr1_off; + uint8_t vxlan_in_saddr1; + }; + union { + uint8_t route_hdr2_off; + uint8_t vxlan_in_saddr2; + }; + uint8_t nxthdr_off; + union { + uint8_t ipv6_frag_off; + uint8_t vxlan_in_saddr3; + }; + rte_be16_t gross_running_sum; + rte_be16_t running_sum; +}; + +struct dpaa2_psr_result_word8 { + uint8_t psr_err; + union { + uint8_t nxthdr_frag_off; + uint8_t vxlan_in_saddr4; + }; + union { + uint8_t ip_n_pid_off; + uint8_t vxlan_in_saddr5; + }; + union __rte_packed_begin { + uint8_t sp_psr_ctx[DPAA2_SP_PSR_CTX_LEN]; + struct __rte_packed_begin { + uint8_t vxlan_vni[3]; + rte_be16_t vxlan_eth_type; + } __rte_packed_end; + union dpaa2_sp_ecpri_msg ecpri_msg; + struct dpaa2_sp_rocev2 rocev2; + struct dpaa2_sp_geneve geneve; + } __rte_packed_end; +}; + +struct __rte_packed_begin dpaa2_psr_result_parse { + struct dpaa2_psr_result_word3 word3; + struct dpaa2_psr_result_word4 word4; + struct dpaa2_psr_result_word5 word5; + struct dpaa2_psr_result_word6 word6; + struct dpaa2_psr_result_word7 word7; + struct dpaa2_psr_result_word8 word8; +} __rte_packed_end; + +#define DPAA2_PSR_RESULT_SIZE sizeof(struct dpaa2_psr_result_parse) + +#define DPAA2_FAFE_PSR_RESULT_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word3.fafe) + +union __rte_packed_begin dpaa2_sp_fafe_parse_8b { + uint8_t fafe_8b; + union dpaa2_sp_fafe_parse fafe; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_l_parse_32b { + uint32_t faf_l_32b; + struct dpaa2_faf_l_parse faf_l; +} __rte_packed_end; + +union __rte_packed_begin dpaa2_faf_h_parse_64b { + uint64_t faf_h_64b; + struct dpaa2_faf_h_parse faf_h; +} __rte_packed_end; + +/* Set by SP for vxlan distribution start*/ +#define DPAA2_VXLAN_IN_TCI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_vlan_tci) +#define DPAA2_VXLAN_IN_DADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr0) +#define DPAA2_VXLAN_IN_DADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word5.vxlan_in_daddr1) +#define DPAA2_VXLAN_IN_DADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr2) +#define DPAA2_VXLAN_IN_DADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr3) +#define DPAA2_VXLAN_IN_DADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr4) +#define DPAA2_VXLAN_IN_DADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_daddr5) + +#define DPAA2_VXLAN_IN_SADDR0_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word6.vxlan_in_saddr0) +#define DPAA2_VXLAN_IN_SADDR1_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr1) +#define DPAA2_VXLAN_IN_SADDR2_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr2) +#define DPAA2_VXLAN_IN_SADDR3_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word7.vxlan_in_saddr3) +#define DPAA2_VXLAN_IN_SADDR4_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr4) +#define DPAA2_VXLAN_IN_SADDR5_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) + +#define DPAA2_VXLAN_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) +#define DPAA2_VXLAN_IN_TYPE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) +/* Set by SP for vxlan distribution end*/ + +#define DPAA2_ECPRI_MSG_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.ecpri_msg) + +#define DPAA2_ROCEV2_OPCODE_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.opcode) + +#define DPAA2_ROCEV2_DST_QP_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.rocev2.dest_qp[0]) + +#define DPAA2_GENEVE_PROTOCOL_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.protocol) + +#define DPAA2_GENEVE_VNI_OFFSET \ + offsetof(struct dpaa2_psr_result_parse, word8.geneve.geneve_vni[0]) + +static inline uint32_t +dpaa2_spsr_fafe_bit_offset(union dpaa2_sp_fafe_parse fafe) +{ + union dpaa2_sp_fafe_parse_8b fafe_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_sp_fafe_parse_8b); + + memset(&fafe_tmp, 0, sizeof(union dpaa2_sp_fafe_parse_8b)); + fafe_tmp.fafe_8b = 1; + while (memcmp(&fafe_tmp.fafe, &fafe, + sizeof(union dpaa2_sp_fafe_parse))) { + fafe_tmp.fafe_8b = fafe_tmp.fafe_8b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, word3.fafe); +} + +static inline uint32_t +dpaa2_psr_faf_l_bit_offset(struct dpaa2_faf_l_parse *faf_l) +{ + union dpaa2_faf_l_parse_32b faf_l_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_l_parse_32b); + + memset(&faf_l_tmp, 0, sizeof(union dpaa2_faf_l_parse_32b)); + faf_l_tmp.faf_l_32b = 1; + while (memcmp(&faf_l_tmp.faf_l, faf_l, + sizeof(struct dpaa2_faf_l_parse))) { + faf_l_tmp.faf_l_32b = faf_l_tmp.faf_l_32b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word3.faf_l_be); +} + +static inline uint32_t +dpaa2_psr_faf_h_bit_offset(struct dpaa2_faf_h_parse *faf_h) +{ + union dpaa2_faf_h_parse_64b faf_h_tmp; + uint32_t offset = BIT_LAST_OFFSET(union dpaa2_faf_h_parse_64b); + + memset(&faf_h_tmp, 0, sizeof(union dpaa2_faf_h_parse_64b)); + faf_h_tmp.faf_h_64b = 1; + while (memcmp(&faf_h_tmp.faf_h, faf_h, + sizeof(struct dpaa2_faf_h_parse))) { + faf_h_tmp.faf_h_64b = faf_h_tmp.faf_h_64b << 1; + offset--; + } + return offset + BIT_OFFSET(struct dpaa2_psr_result_parse, + word4.faf_h_be); +} + +static inline int +dpaa2_protocol_psr_bit_offset(uint32_t *bit_offset, + enum dpaa2_parser_protocol_id protocol) +{ + struct dpaa2_faf_l_parse faf_l; + struct dpaa2_faf_h_parse faf_h; + union dpaa2_sp_fafe_parse fafe; + + memset(&faf_l, 0, sizeof(faf_l)); + memset(&faf_h, 0, sizeof(faf_h)); + memset(&fafe, 0, sizeof(fafe)); + + if (protocol == DPAA2_PARSER_MAC_ID) { + faf_l.mac = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_VLAN_ID) { + faf_l.vlan_1 = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_ICMP_ID) { + faf_h.icmp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_ID) { + faf_h.ip_1_opt = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV4_ID) { + faf_h.ipv4_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IP_FRAG_ID) { + faf_h.ip_1_frag = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPV6_ID) { + faf_h.ipv6_1 = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GRE_ID) { + faf_h.gre = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_UDP_ID) { + faf_h.udp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_TCP_ID) { + faf_h.tcp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_SCTP_ID) { + faf_h.sctp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_GTP_ID) { + faf_h.gtp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_ESP_ID) { + faf_h.ipsec_esp = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_IPSEC_AH_ID) { + faf_h.ipsec_ah = 1; + *bit_offset = dpaa2_psr_faf_h_bit_offset(&faf_h); + } else if (protocol == DPAA2_PARSER_VXLAN_ID) { + faf_l.vxlan = 1; + *bit_offset = dpaa2_psr_faf_l_bit_offset(&faf_l); + } else if (protocol == DPAA2_PARSER_TUNNEL_VLAN_ID) { + fafe.rocev2_tunnel.in_vlan = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV4_ID) { + fafe.rocev2_tunnel.in_ipv4 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_IPV6_ID) { + fafe.rocev2_tunnel.in_ipv6 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_UDP_ID) { + fafe.rocev2_tunnel.in_udp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_TUNNEL_TCP_ID) { + fafe.rocev2_tunnel.in_tcp = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ECPRI_ID) { + fafe.ecpri.ecpri = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_ROCEV2_ID) { + fafe.rocev2_tunnel.rocev2 = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else if (protocol == DPAA2_PARSER_GENEVE_ID) { + fafe.rocev2_tunnel.geneve = 1; + *bit_offset = dpaa2_spsr_fafe_bit_offset(fafe); + } else { + DPAA2_PMD_ERR("Unsupported parser protocol(%d)", protocol); + return -ENOTSUP; + } + + return 0; +} + +static inline uint32_t __rte_hot +dpaa2_dev_rx_parse_frc(const struct qbman_fd *fd, + struct rte_mbuf *m, + const struct dpaa2_annot_hdr *annotation) +{ + const struct dpaa2_ingress_frc *frc = (const void *)&fd->simple.frc; + const struct dpaa2_psr_summary *sum = &frc->psr_sum.sum; + const union dpaa2_psr_summary_l *sum_l = &sum->sum_l; + int ip4_6 = 0, vxlan = 0; + struct dpaa2_annot_hdr annot_convert; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + uint32_t packet_type = RTE_PTYPE_UNKNOWN; + uint8_t vlan_offset; + rte_be16_t *vlan_tci; + + /**Access annotation only for vlan and checksum error.*/ + + if (sum->vlan) { + annot_convert.word5 = annotation->word5; + annot_convert.word5 = rte_cpu_to_be_64(annot_convert.word5); + psr = (const void *)&annot_convert.word3; + packet_type |= RTE_PTYPE_L2_ETHER_VLAN; + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + if (sum->vlan > 1) { + vlan_offset = psr->word5.vlan_tci_n_off; + packet_type |= RTE_PTYPE_L2_ETHER_QINQ; + m->ol_flags |= RTE_MBUF_F_RX_QINQ; + } else { + vlan_offset = psr->word5.vlan_tci_1_off; + } + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, vlan_offset); + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); + } + if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4) { + packet_type |= RTE_PTYPE_L3_IPV4; + ip4_6 = 1; + } else if (sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV6) { + packet_type |= RTE_PTYPE_L3_IPV6; + ip4_6 = 1; + } + + /* Non-VLAN IP frames need RTE_PTYPE_L2_ETHER; VLAN frames + * already have L2_ETHER_VLAN set above. + */ + if (ip4_6 && !sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + + if (ip4_6) { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) { + packet_type |= RTE_PTYPE_L4_FRAG; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) { + packet_type |= RTE_PTYPE_L4_ICMP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) { + packet_type |= RTE_PTYPE_TUNNEL_ESP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) { + packet_type |= RTE_PTYPE_L4_TCP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) { + packet_type |= RTE_PTYPE_L4_UDP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) { + packet_type |= RTE_PTYPE_L4_SCTP; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + } else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) { + packet_type |= RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_VXLAN; + vxlan = 1; + } else { + packet_type |= RTE_PTYPE_L4_NONFRAG; + } + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + if (!sum->vlan) + packet_type |= RTE_PTYPE_L2_ETHER; + if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4) + packet_type |= RTE_PTYPE_L3_IPV4; + else if (sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV6) + packet_type |= RTE_PTYPE_L3_IPV6; + if (sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV4 || + sum_l->l4_ext.l4_ext == DPAA2_PSR_SUMMARY_GRE_IPV6) + packet_type |= RTE_PTYPE_TUNNEL_GRE; + else if (sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV4_UDP_TCP || + sum_l->l4_ext.l4_ext == + DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) + packet_type |= RTE_PTYPE_TUNNEL_NVGRE; + } else if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP) { + packet_type |= RTE_PTYPE_L2_ETHER_ARP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP) { + packet_type |= RTE_PTYPE_L2_ETHER_TIMESYNC; + m->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP; + } else if (sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_MPLS) { + packet_type |= RTE_PTYPE_L2_ETHER_MPLS; + } + } + + if (unlikely(sum->checksum_err)) { + fas = (const void *)&annotation->word1; + if (fas->l3ce) + m->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; + if (fas->l4ce) + m->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD; + } + + /* + * fafe0 (eCPRI) and fafe1 (RoCEv2) are reported by the soft parser but + * have no matching RTE_PTYPE value, so only the VXLAN inner types are + * translated here. + */ + if (!sum->fafe0 && !sum->fafe1 && vxlan) { + if (sum->fafe2) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } else if (sum_l->l4.fafe3) { + packet_type |= RTE_PTYPE_INNER_L2_ETHER; + packet_type |= RTE_PTYPE_INNER_L3_IPV6; + } + } + + return packet_type; +} + +#define DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule, mask, size, offset, nb, max, \ + rule_val, mask_val, size_val, offset_val) \ +({ \ + uint64_t *_rule = (rule); \ + uint64_t *_mask = (mask); \ + uint8_t *_size = (size); \ + uint8_t *_offset = (offset); \ + int _ecpri_ret = 0; \ + int _nb = (nb); \ + \ + if (_nb >= (max)) { \ + _ecpri_ret = -ENOSPC; \ + } else { \ + _rule[_nb] = (rule_val); \ + _mask[_nb] = (mask_val); \ + _size[_nb] = (size_val); \ + _offset[_nb] = (offset_val); \ + } \ + _ecpri_ret; \ +}) + +static inline int +dpaa2_parser_ecpri_extract(const struct rte_flow_item_ecpri *spec, + const struct rte_flow_item_ecpri *mask, + uint64_t rule_data[], uint64_t mask_data[], + uint8_t extract_size[], uint8_t extract_off[], + union dpaa2_sp_fafe_parse *fafe, uint8_t max_nb) +{ + int extract_nb = 0, ret; + + if (mask->hdr.common.type != 0xff) { + DPAA2_PR_PRINT("ECPRI header type not specified."); + + return -EINVAL; + } + + if (spec->hdr.common.type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("ECPRI header type(%d) not supported.", + spec->hdr.common.type); + + return -ENOTSUP; + } + + /** Extract eCPRI type from FAFE.*/ + fafe->ecpri.ecpri = 1; + fafe->ecpri.msg_type = spec->hdr.common.type; + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, fafe->fafe_8b, 0xff, sizeof(uint8_t), + DPAA2_FAFE_PSR_RESULT_OFFSET); + if (ret) + return ret; + extract_nb++; + + if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { + if (mask->hdr.type0.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.pc_id, + mask->hdr.type0.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type0.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type0.seq_id, + mask->hdr.type0.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_iq_data, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + if (mask->hdr.type1.pc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.pc_id, + mask->hdr.type1.pc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, pc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type1.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type1.seq_id, + mask->hdr.type1.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_bit_seq, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + if (mask->hdr.type2.rtc_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.rtc_id, + mask->hdr.type2.rtc_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type2.seq_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type2.seq_id, + mask->hdr.type2.seq_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) + DPAA2_PMD_WARN("Extract type3 msg not support."); + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + if (mask->hdr.type4.rma_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.rma_id, + mask->hdr.type4.rma_id, sizeof(uint8_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 0); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type4.ele_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type4.ele_id, + mask->hdr.type4.ele_id, sizeof(rte_be16_t), + /** Compiler can't support to take address + * of bit-field + * offsetof(struct rte_ecpri_msg_rm_access, + * rma_id); + */ + DPAA2_ECPRI_MSG_OFFSET + 2); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + if (mask->hdr.type5.msr_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.msr_id, + mask->hdr.type5.msr_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, msr_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type5.act_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type5.act_type, + mask->hdr.type5.act_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_delay_measure, act_type)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + if (mask->hdr.type6.rst_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_id, + mask->hdr.type6.rst_id, sizeof(rte_be16_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type6.rst_op) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type6.rst_op, + mask->hdr.type6.rst_op, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_remote_reset, rst_op)); + if (ret) + return ret; + extract_nb++; + } + } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + if (mask->hdr.type7.evt_id) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_id, + mask->hdr.type7.evt_id, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_id)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.evt_type) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.evt_type, + mask->hdr.type7.evt_type, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, evt_type)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.seq) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.seq, + mask->hdr.type7.seq, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, seq)); + if (ret) + return ret; + extract_nb++; + } + if (mask->hdr.type7.number) { + ret = DPAA2_PARSER_ECPRI_EXTRACT_SAFE(rule_data, mask_data, extract_size, + extract_off, extract_nb, max_nb, spec->hdr.type7.number, + mask->hdr.type7.number, sizeof(uint8_t), + DPAA2_ECPRI_MSG_OFFSET + + offsetof(struct rte_ecpri_msg_event_ind, number)); + if (ret) + return ret; + extract_nb++; + } + } else { + DPAA2_PR_PRINT("Unsupported ecpri header type(%d)", + spec->hdr.common.type); + return -ENOTSUP; + } + + return extract_nb; +} + +static inline void +dpaa2_print_rocev2_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + int i; + + DPAA2_PR_PRINT("ROCEv2 opcode: 0x%02x\r\n", psr->word8.rocev2.opcode); + DPAA2_PR_PRINT("ROCEv2 qp: "); + for (i = 0; i < ROCEV2_DEST_QP_SIZE; i++) + DPAA2_PR_PRINT("0x%02x ", psr->word8.rocev2.dest_qp[i]); + + DPAA2_PR_PRINT("\r\n"); +} + +static inline void +dpaa2_print_geneve_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + DPAA2_PR_PRINT("GENEVE protocol: 0x%04x\r\n", + rte_be_to_cpu_16(psr->word8.geneve.protocol)); + DPAA2_PR_PRINT("GENEVE vni: %02x %02x %02x\r\n", + psr->word8.geneve.geneve_vni[0], + psr->word8.geneve.geneve_vni[1], + psr->word8.geneve.geneve_vni[2]); +} + +static inline void +dpaa2_print_vxlan_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + struct rte_ether_hdr vxlan_in_eth; + uint16_t vxlan_vlan_tci, i; + + vxlan_in_eth.dst_addr.addr_bytes[0] = psr->word5.vxlan_in_daddr0; + vxlan_in_eth.dst_addr.addr_bytes[1] = psr->word5.vxlan_in_daddr1; + vxlan_in_eth.dst_addr.addr_bytes[2] = psr->word6.vxlan_in_daddr2; + vxlan_in_eth.dst_addr.addr_bytes[3] = psr->word6.vxlan_in_daddr3; + vxlan_in_eth.dst_addr.addr_bytes[4] = psr->word6.vxlan_in_daddr4; + vxlan_in_eth.dst_addr.addr_bytes[5] = psr->word6.vxlan_in_daddr5; + + vxlan_in_eth.src_addr.addr_bytes[0] = psr->word6.vxlan_in_saddr0; + vxlan_in_eth.src_addr.addr_bytes[1] = psr->word7.vxlan_in_saddr1; + vxlan_in_eth.src_addr.addr_bytes[2] = psr->word7.vxlan_in_saddr2; + vxlan_in_eth.src_addr.addr_bytes[3] = psr->word7.vxlan_in_saddr3; + vxlan_in_eth.src_addr.addr_bytes[4] = psr->word8.vxlan_in_saddr4; + vxlan_in_eth.src_addr.addr_bytes[5] = psr->word8.vxlan_in_saddr5; + + vxlan_in_eth.ether_type = psr->word8.vxlan_eth_type; + vxlan_in_eth.ether_type = rte_be_to_cpu_16(vxlan_in_eth.ether_type); + + DPAA2_PR_PRINT("VXLAN inner eth:\r\n"); + DPAA2_PR_PRINT("dst addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.dst_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("src addr: "); + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + if (i != 0) + DPAA2_PR_PRINT(":"); + DPAA2_PR_PRINT("%02x", vxlan_in_eth.src_addr.addr_bytes[i]); + } + DPAA2_PR_PRINT("\r\n"); + DPAA2_PR_PRINT("type: 0x%04x\r\n", vxlan_in_eth.ether_type); + if (vxlan_in_eth.ether_type == RTE_ETHER_TYPE_VLAN) { + rte_memcpy(&vxlan_vlan_tci, + &psr->word5.vxlan_vlan_tci, sizeof(uint16_t)); + vxlan_vlan_tci = rte_be_to_cpu_16(vxlan_vlan_tci); + DPAA2_PR_PRINT("vlan tci: 0x%04x\r\n", vxlan_vlan_tci); + } +} + +static inline void +dpaa2_print_ecpri_parse_result(const struct dpaa2_psr_result_parse *psr) +{ + uint8_t msg_type; + struct rte_ecpri_combined_msg_hdr ecpri_msg; + + msg_type = psr->word3.fafe.ecpri.msg_type; + if (msg_type > RTE_ECPRI_MSG_TYPE_IWF_DCTRL) { + DPAA2_PR_PRINT("Invalid ECPRI message type(0x%02x)\r\n", + msg_type); + return; + } + + DPAA2_PR_PRINT("ECPRI type %d present\r\n", msg_type); + rte_memcpy(ecpri_msg.dummy, psr->word8.sp_psr_ctx, + DPAA2_SP_PSR_CTX_LEN); + if (msg_type == RTE_ECPRI_MSG_TYPE_IQ_DATA || + msg_type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { + DPAA2_PR_PRINT("pc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type0.pc_id), + rte_be_to_cpu_16(ecpri_msg.type0.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { + DPAA2_PR_PRINT("rtc_id(0x%04x) seq_id(0x%04x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type2.rtc_id), + rte_be_to_cpu_16(ecpri_msg.type2.seq_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { + DPAA2_PR_PRINT("ECPRI type3 extract not support\r\n"); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RM_ACC) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)", + ecpri_msg.type4.rma_id, ecpri_msg.type4.rw); + DPAA2_PR_PRINT(" rr(0x%02x) ele_id(0x%04x)\r\n", + ecpri_msg.type4.rr, + rte_be_to_cpu_16(ecpri_msg.type4.ele_id)); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { + DPAA2_PR_PRINT("rma_id(0x%02x) rw(0x%02x)\r\n", + ecpri_msg.type5.msr_id, + ecpri_msg.type5.act_type); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_RMT_RST) { + DPAA2_PR_PRINT("rst_id(0x%04x) rst_op(0x%02x)\r\n", + rte_be_to_cpu_16(ecpri_msg.type6.rst_id), + ecpri_msg.type6.rst_op); + } else if (msg_type == RTE_ECPRI_MSG_TYPE_EVT_IND) { + DPAA2_PR_PRINT("evt_id(0x%02x) evt_type(0x%02x)", + ecpri_msg.type7.evt_id, + ecpri_msg.type7.evt_type); + DPAA2_PR_PRINT(" seq(0x%02x) number(0x%02x)\r\n", + ecpri_msg.type7.seq, + ecpri_msg.type7.number); + } +} + +static inline void +dpaa2_print_fd_frc(const struct qbman_fd *fd) +{ + const struct dpaa2_ingress_frc *frc; + const struct dpaa2_psr_summary *sum; + const union dpaa2_psr_summary_l *sum_l; + const char *l4_nm; + + frc = (const void *)&fd->simple.frc; + DPAA2_PR_PRINT("FRC faicfdv: %d\r\n", frc->faicfdv); + DPAA2_PR_PRINT("FRC faswov: %d\r\n", frc->faswov); + DPAA2_PR_PRINT("FRC faiadv: %d\r\n", frc->faiadv); + DPAA2_PR_PRINT("FRC faprv: %d\r\n", frc->faprv); + DPAA2_PR_PRINT("FRC faeadv: %d\r\n", frc->faeadv); + DPAA2_PR_PRINT("FRC fasv: %d\r\n", frc->fasv); + + sum = &frc->psr_sum.sum; + sum_l = &sum->sum_l; + DPAA2_PR_PRINT("FRC Check sum err: %d\r\n", sum->checksum_err); + DPAA2_PR_PRINT("FRC vlan: %d\r\n", sum->vlan); + if (sum_l->non_ip.non_ip == DPAA2_PSR_SUMMARY_NONIP) { + DPAA2_PR_PRINT("FRC NON IP %s detected, l2: %d\r\n", + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_ARP ? + "arp" : + sum_l->non_ip.l2 == DPAA2_PSR_SUMMARY_NONIP_PTP ? + "ptp" : "", + sum_l->non_ip.l2); + } else if (sum_l->l4_ext.l3 == DPAA2_PSR_SUMMARY_L4_EXT) { + DPAA2_PR_PRINT("FRC L4 ext %s (%d) detected\r\n", + sum_l->l4_ext.ip == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4_ext.l4_ext); + } else { + if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IP_FRAG) + l4_nm = "fragment"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_ICMP) + l4_nm = "icmp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_IPSEC_ESP) + l4_nm = "IPSec ESP"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_TCP) + l4_nm = "tcp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_SCTP) + l4_nm = "sctp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP) + l4_nm = "udp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_PTP) + l4_nm = "ptp"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_UDP_ESP_IKE) + l4_nm = "udp/esp/ike"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPU) + l4_nm = "gtpu"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_GTPC) + l4_nm = "gtpc"; + else if (sum_l->l4.l4 == DPAA2_PSR_SUMMARY_VXLAN) + l4_nm = "vxlan"; + else + l4_nm = ""; + DPAA2_PR_PRINT("FRC %s(%d) %s(%d) detected\r\n", + sum_l->l4.l3 == DPAA2_PSR_SUMMARY_IPV4 ? + "ipv4" : "ipv6", sum_l->l4.l3, + l4_nm, sum_l->l4.l4); + } + + DPAA2_PR_PRINT("FRC FAFE bit0~3: %d%d%d%d\r\n", + sum->fafe0, sum->fafe1, sum->fafe2, sum_l->l4.fafe3); +} + +static inline void +dpaa2_print_parse_result(const struct dpaa2_annot_hdr *annotation, + int is_sp) +{ + struct dpaa2_annot_hdr annot_convert; + uint64_t annot_size = sizeof(struct dpaa2_annot_hdr), offset = 0; + uint64_t *word; + const struct dpaa2_psr_result_parse *psr; + const struct dpaa2_fas_parse *fas; + + rte_memcpy(&annot_convert, annotation, sizeof(struct dpaa2_annot_hdr)); + while (annot_size) { + word = (uint64_t *)&annot_convert + offset; + *word = rte_cpu_to_be_64(*word); + offset++; + annot_size -= sizeof(uint64_t); + } + fas = (const void *)&annotation->word1; + psr = (const void *)&annot_convert.word3; + + if (fas->discard) + DPAA2_PR_PRINT("FAS discard\r\n"); + if (fas->macsec) + DPAA2_PR_PRINT("FAS MACSEC present\r\n"); + if (fas->ptp) + DPAA2_PR_PRINT("FAS PTP present\r\n"); + if (fas->multicast) + DPAA2_PR_PRINT("FAS Multicast present\r\n"); + if (fas->broadcast) + DPAA2_PR_PRINT("FAS Broadcast present\r\n"); + if (fas->kse) + DPAA2_PR_PRINT("FAS Invalid key or key size error\r\n"); + if (fas->eofhe) + DPAA2_PR_PRINT("FAS extract out of frame header\r\n"); + if (fas->mnle) + DPAA2_PR_PRINT("FAS Max number of chained lookups reached\r\n"); + if (fas->tide) + DPAA2_PR_PRINT("FAS Invalid table ID\r\n"); + if (fas->piee) + DPAA2_PR_PRINT("FAS Policer Initialization Entry Error\r\n"); + if (fas->fle) + DPAA2_PR_PRINT("FAS Frame Length Error\r\n"); + if (fas->fpe) + DPAA2_PR_PRINT("FAS Frame physical Error\r\n"); + if (fas->pte) + DPAA2_PR_PRINT("FAS Parser terminate early\r\n"); + if (fas->isp) + DPAA2_PR_PRINT("FAS Invalid SP instruction is encountered\r\n"); + if (fas->phe) + DPAA2_PR_PRINT("FAS Error during parsing\r\n"); + if (fas->ble) + DPAA2_PR_PRINT("FAS block limit is exceeded\r\n"); + if (fas->l3cv) + DPAA2_PR_PRINT("FAS L3 checksum validation is performed\r\n"); + if (fas->l3ce) + DPAA2_PR_PRINT("FAS L3 checksum error detected\r\n"); + if (fas->l4cv) + DPAA2_PR_PRINT("FAS L4 checksum validation is performed\r\n"); + if (fas->l4ce) + DPAA2_PR_PRINT("FAS L4 checksum error detected\r\n"); + DPAA2_PR_PRINT("FAS IFPID:%d PPID:%d, status:%02x\r\n", + fas->ifpid, fas->ppid, fas->status); + + /** FAF error dump.*/ + if (psr->word3.faf_l_be.arp_err) + DPAA2_PR_PRINT("FAF ARP error detected\r\n"); + if (psr->word3.faf_l_be.mpls_err) + DPAA2_PR_PRINT("FAF MPLS error detected\r\n"); + if (psr->word3.faf_l_be.pppoe_ppp_err) + DPAA2_PR_PRINT("FAF PPPOE/PPP error detected\r\n"); + if (psr->word3.faf_l_be.vlan_err) + DPAA2_PR_PRINT("FAF vLAN error detected\r\n"); + if (psr->word3.faf_l_be.llc_snap_err) + DPAA2_PR_PRINT("FAF LLC/SNAP error detected\r\n"); + if (psr->word3.faf_l_be.eth_err) + DPAA2_PR_PRINT("FAF Ethernet error detected\r\n"); + if (psr->word3.faf_l_be.psr_err) + DPAA2_PR_PRINT("FAF Parser error detected\r\n"); + if (psr->word3.faf_l_be.spsr_err) + DPAA2_PR_PRINT("FAF Soft Parser error detected\r\n"); + if (psr->word3.faf_l_be.vxlan_err) + DPAA2_PR_PRINT("FAF VXLan error detected\r\n"); + if (psr->word4.faf_h_be.esp_err) + DPAA2_PR_PRINT("FAF ESP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.gtp_err) + DPAA2_PR_PRINT("FAF GTP error detected\r\n"); + if (psr->word4.faf_h_be.l4_spsr_err) + DPAA2_PR_PRINT("FAF L4 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.sctp_err) + DPAA2_PR_PRINT("FAF SCTP error detected\r\n"); + if (psr->word4.faf_h_be.ipsec_err) + DPAA2_PR_PRINT("FAF IPSec error detected\r\n"); + if (psr->word4.faf_h_be.tcp_err) + DPAA2_PR_PRINT("FAF TCP error detected\r\n"); + if (psr->word4.faf_h_be.udp_err) + DPAA2_PR_PRINT("FAF UDP error detected\r\n"); + if (psr->word4.faf_h_be.l3_spsr_err) + DPAA2_PR_PRINT("FAF L3 soft Parser error detected\r\n"); + if (psr->word4.faf_h_be.gre_err) + DPAA2_PR_PRINT("FAF GRE error detected\r\n"); + if (psr->word4.faf_h_be.min_encp_err) + DPAA2_PR_PRINT("FAF Min.Encap error detected\r\n"); + if (psr->word4.faf_h_be.ip_n_err) + DPAA2_PR_PRINT("FAF IP.n error detected\r\n"); + if (psr->word4.faf_h_be.ip_1_err) + DPAA2_PR_PRINT("FAF IP.1 error detected\r\n"); + if (psr->word4.faf_h_be.l2_spsr_err) + DPAA2_PR_PRINT("FAF L2 soft parser error detected\r\n"); + + DPAA2_PR_PRINT("Next Header: %04x\r\n", + rte_be_to_cpu_16(psr->word3.nxthdr)); + + if (is_sp) { + if (psr->word3.fafe.ecpri.ecpri) { + DPAA2_PR_PRINT("FAFE ECPRI present, msg: %d\r\n", + psr->word3.fafe.ecpri.msg_type); + } else if (psr->word3.fafe.rocev2_tunnel.rocev2) { + DPAA2_PR_PRINT("FAFE ROCEV2 present\r\n"); + } else if (psr->word3.fafe.rocev2_tunnel.geneve) { + DPAA2_PR_PRINT("FAFE GENEVE present\r\n"); + } else { + if (psr->word3.fafe.rocev2_tunnel.in_vlan) + DPAA2_PR_PRINT("FAFE TUNNEL vLAN present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv4) + DPAA2_PR_PRINT("FAFE TUNNEL IPv4 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_ipv6) + DPAA2_PR_PRINT("FAFE TUNNEL IPv6 present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_udp) + DPAA2_PR_PRINT("FAFE TUNNEL UDP present\r\n"); + if (psr->word3.fafe.rocev2_tunnel.in_tcp) + DPAA2_PR_PRINT("FAFE TUNNEL TCP present\r\n"); + } + } else { + DPAA2_PR_PRINT("FAFE: 0x%02x\r\n", psr->word3.fafe.fafe_8b); + } + + /** FAF popular protocol dump.*/ + if (psr->word3.faf_l_be.arp) + DPAA2_PR_PRINT("FAF ARP Present\r\n"); + if (psr->word3.faf_l_be.mac) + DPAA2_PR_PRINT("FAF Ethernet MAC Present\r\n"); + if (psr->word3.faf_l_be.vxlan) + DPAA2_PR_PRINT("FAF VXLan Present\r\n"); + if (psr->word3.faf_l_be.ike) + DPAA2_PR_PRINT("FAF IKE Present\r\n"); + if (psr->word3.faf_l_be.ptp) + DPAA2_PR_PRINT("FAF PTP Present\r\n"); + if (psr->word4.faf_h_be.gtp) + DPAA2_PR_PRINT("FAF GTP Present\r\n"); + if (psr->word4.faf_h_be.sctp) + DPAA2_PR_PRINT("FAF SCTP Present\r\n"); + if (psr->word4.faf_h_be.ipsec) + DPAA2_PR_PRINT("FAF IPSec Present\r\n"); + if (psr->word4.faf_h_be.ipsec_esp) + DPAA2_PR_PRINT("FAF IPSec ESP Present\r\n"); + if (psr->word4.faf_h_be.ipsec_ah) + DPAA2_PR_PRINT("FAF IPSec AH Present\r\n"); + if (psr->word4.faf_h_be.gre) + DPAA2_PR_PRINT("FAF GRE Present\r\n"); + if (psr->word4.faf_h_be.icmp) + DPAA2_PR_PRINT("FAF ICMP Present\r\n"); + if (psr->word4.faf_h_be.ipv6_1) + DPAA2_PR_PRINT("FAF IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv6_n) + DPAA2_PR_PRINT("FAF last IPv6 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_1) + DPAA2_PR_PRINT("FAF IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ipv4_n) + DPAA2_PR_PRINT("FAF last IPv4 Present\r\n"); + if (psr->word4.faf_h_be.ip_1_opt) + DPAA2_PR_PRINT("FAF IP Present\r\n"); + if (psr->word4.faf_h_be.ip_1_init_frag) + DPAA2_PR_PRINT("FAF IP first fragment Present\r\n"); + if (psr->word4.faf_h_be.ip_1_frag) + DPAA2_PR_PRINT("FAF IP fragment Present\r\n"); + if (psr->word4.faf_h_be.tcp) + DPAA2_PR_PRINT("FAF TCP Present\r\n"); + if (psr->word4.faf_h_be.udp) + DPAA2_PR_PRINT("FAF UDP Present\r\n"); + + DPAA2_PR_PRINT("Parser result eth header offset: %02x\r\n", + psr->word5.eth_off); + DPAA2_PR_PRINT("Parser result TCI1 offset: %02x\r\n", + psr->word5.vlan_tci_1_off); + DPAA2_PR_PRINT("Parser result last eth type offset: %02x\r\n", + psr->word5.last_etype_off); + DPAA2_PR_PRINT("Parser result l3 header offset: %02x\r\n", + psr->word6.l3_off); + DPAA2_PR_PRINT("Parser result l4 header offset: %02x\r\n", + psr->word6.l4_off); + DPAA2_PR_PRINT("Parser result l5 header offset: %02x\r\n", + psr->word6.l5_off); + DPAA2_PR_PRINT("Parser result next header offset: %02x\r\n", + psr->word7.nxthdr_off); + + if (is_sp) { + if (psr->word3.faf_l_be.vxlan) + dpaa2_print_vxlan_parse_result(psr); + if (psr->word3.fafe.ecpri.ecpri) + dpaa2_print_ecpri_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.rocev2) + dpaa2_print_rocev2_parse_result(psr); + if (psr->word3.fafe.rocev2_tunnel.geneve) + dpaa2_print_geneve_parse_result(psr); + } +} + +#endif /* _DPAA2_PARSE_DECODE_H */ diff --git a/drivers/net/dpaa2/dpaa2_pmd_logs.h b/drivers/net/dpaa2/dpaa2_pmd_logs.h index 28c9bed1ae..f1148f5b8d 100644 --- a/drivers/net/dpaa2/dpaa2_pmd_logs.h +++ b/drivers/net/dpaa2/dpaa2_pmd_logs.h @@ -5,6 +5,13 @@ #ifndef _DPAA2_PMD_LOGS_H_ #define _DPAA2_PMD_LOGS_H_ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_log.h> + extern int dpaa2_logtype_pmd; #define RTE_LOGTYPE_DPAA2_NET dpaa2_logtype_pmd @@ -36,4 +43,64 @@ extern int dpaa2_logtype_pmd; #define DPAA2_PMD_DP_WARN(fmt, ...) \ DPAA2_PMD_DP_LOG(WARNING, fmt, ## __VA_ARGS__) +/** Maximum length of a single debug dump line. */ +#define DPAA2_DUMP_LINE_SIZE 512 + +/** + * Append formatted text to the per-thread debug dump line buffer. + * + * The parse result and flow dump helpers build a line from several + * fragments, so the text is accumulated here and handed to the regular + * logging framework one complete line at a time. This keeps the dump + * readable without writing to stdout or stderr from the driver. + * + * Carriage returns and newlines terminate a line and are not logged. + */ +static inline void +dpaa2_dump_print(const char *fmt, ...) __rte_format_printf(1, 2); + +static inline void +dpaa2_dump_print(const char *fmt, ...) +{ + static __thread char line[DPAA2_DUMP_LINE_SIZE]; + static __thread size_t used; + size_t start, i; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(line + used, sizeof(line) - used, fmt, ap); + va_end(ap); + + if (len > 0) { + used += (size_t)len; + /* Output was truncated, keep the buffer consistent. */ + if (used >= sizeof(line)) + used = sizeof(line) - 1; + } + + /* Log every complete line held in the buffer. */ + start = 0; + for (i = 0; i < used; i++) { + if (line[i] != '\n' && line[i] != '\r') + continue; + line[i] = '\0'; + if (i != start) + DPAA2_PMD_DEBUG("%s", &line[start]); + start = i + 1; + } + + if (start) { + used -= start; + memmove(line, &line[start], used); + } + + /* Flush a full buffer even without a line terminator. */ + if (used >= sizeof(line) - 1) { + line[used] = '\0'; + DPAA2_PMD_DEBUG("%s", line); + used = 0; + } +} + #endif /* _DPAA2_PMD_LOGS_H_ */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 62565486a7..8518541236 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -26,13 +26,7 @@ #include "dpaa2_pmd_logs.h" #include "dpaa2_ethdev.h" #include "base/dpaa2_hw_dpni_annot.h" -#include "dpaa2_parse_dump.h" - -static inline uint32_t __rte_hot -dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, - struct dpaa2_annot_hdr *annotation); - -static void enable_tx_tstamp(struct qbman_fd *fd) __rte_unused; +#include "dpaa2_parser_decode.h" static inline rte_mbuf_timestamp_t * dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) @@ -41,6 +35,43 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) dpaa2_timestamp_dynfield_offset, rte_mbuf_timestamp_t *); } +static inline void +dpaa2_dev_rx_annot_prefetch(const struct qbman_fd *fd) +{ + size_t fd_addr; + void *hw_annot_addr; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + hw_annot_addr = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + rte_prefetch0(hw_annot_addr); +} + +static inline void +dpaa2_dev_rx_parse_offset(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, const struct qbman_fd *fd) +{ + size_t fd_addr; + const struct dpaa2_annot_hdr *annotation; + uint64_t word6; + struct dpaa2_psr_result_word6 *decoded; + struct dpaa2_dyn_rx_protocol_pos *pos; + + fd_addr = (size_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); + annotation = (void *)(fd_addr + DPAA2_FD_PTA_SIZE); + + RTE_ASSERT(priv->psr_dynfield_offset >= + offsetof(struct rte_mbuf, dynfield1[0]) && + priv->psr_dynfield_offset < (sizeof(struct rte_mbuf) - + sizeof(struct dpaa2_dyn_rx_protocol_pos))); + pos = (void *)((uint8_t *)mbuf + priv->psr_dynfield_offset); + + word6 = rte_be_to_cpu_64(annotation->word6); + decoded = (void *)&word6; + pos->l3_offset = decoded->l3_off; + pos->l4_offset = decoded->l4_off; + pos->l5_offset = decoded->l5_off; +} + #define DPAA2_MBUF_TO_CONTIG_FD(_mbuf, _fd, _bpid) do { \ DPAA2_SET_FD_ADDR(_fd, DPAA2_MBUF_VADDR_TO_IOVA(_mbuf)); \ DPAA2_SET_FD_LEN(_fd, _mbuf->data_len); \ @@ -51,97 +82,140 @@ dpaa2_timestamp_dynfield(struct rte_mbuf *mbuf) DPAA2_RESET_FD_FLC(_fd); \ } while (0) -static inline void __rte_hot -dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, - void *hw_annot_addr) +static inline void +dpaa2_dev_rx_flc_parse(struct rte_mbuf *m, + const struct qbman_fd *fd) { - uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; uint32_t flc_lo, tc, flow; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); + flc_lo = fd->simple.flc_lo; + + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + + m->ol_flags |= + RTE_MBUF_F_RX_FDIR | + RTE_MBUF_F_RX_FDIR_ID; + m->hash.fdir.hi = (tc << 16) | flow; + + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } +} + +static void __rte_hot +dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, + struct rte_mbuf *m, const struct qbman_fd *fd, + void *hw_annot_addr, int is_vlan) +{ + uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); + struct dpaa2_psr_summary *frc_parse = (void *)&frc; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; + int default_parsed = false, vlan2 = false; + uint32_t ext_packet_type = RTE_PTYPE_UNKNOWN; m->packet_type = RTE_PTYPE_UNKNOWN; + + if (unlikely(is_vlan)) { + if (frc & DPAA2_PKT_TYPE_VLAN_2) + vlan2 = true; + + frc &= (~DPAA2_PKT_TYPE_VLAN); + } + + if (priv->sp_protocol) { + if (frc_parse->fafe2) { + frc_parse->fafe2 = 0; + ext_packet_type |= RTE_PTYPE_TUNNEL_GENEVE; + } + + if (frc_parse->sum_l.l4.fafe3) { + frc_parse->sum_l.l4.fafe3 = 0; + ext_packet_type |= RTE_PTYPE_INNER_L3_IPV4; + } + } + switch (frc) { - case DPAA2_PKT_TYPE_ETHER: - m->packet_type = RTE_PTYPE_L2_ETHER; - break; - case DPAA2_PKT_TYPE_IPV4: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4; - break; - case DPAA2_PKT_TYPE_IPV6: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6; - break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: + case DPAA2_PKT_TYPE_IPV4_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; break; + case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV6_TCP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; - break; - case DPAA2_PKT_TYPE_IPV4_UDP: + + case DPAA2_PKT_TYPE_IPV4: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; + RTE_PTYPE_L3_IPV4; break; + case DPAA2_PKT_TYPE_IPV6_UDP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; break; - case DPAA2_PKT_TYPE_IPV4_SCTP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_SCTP; - break; - case DPAA2_PKT_TYPE_IPV6_SCTP: + + case DPAA2_PKT_TYPE_IPV6_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_SCTP; + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; break; - case DPAA2_PKT_TYPE_IPV4_ICMP: + + case DPAA2_PKT_TYPE_IPV6: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_ICMP; + RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV6_ICMP: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; + + case DPAA2_PKT_TYPE_ETHER: + m->packet_type = RTE_PTYPE_L2_ETHER; break; + default: - m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); + m->packet_type = + dpaa2_dev_rx_parse_frc(fd, m, annotation); + default_parsed = true; + break; } - flc_lo = fd->simple.flc_lo; - if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { - tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & - DPAA2_FS_FLC_TC_MASK; - flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; - m->ol_flags |= - RTE_MBUF_F_RX_FDIR | - RTE_MBUF_F_RX_FDIR_ID; - m->hash.fdir.hi = (tc << 16) | flow; - DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", - tc, flow); - } else { - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; - DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", - m->hash.rss); + + m->packet_type |= ext_packet_type; + + if (unlikely(is_vlan && !default_parsed)) { + struct dpaa2_psr_result_word5 word5; + rte_be16_t *vlan_tci = NULL; + + m->ol_flags |= RTE_MBUF_F_RX_VLAN; + + *(rte_be64_t *)&word5 = + rte_cpu_to_be_64(annotation->word5); + + if (vlan2) { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_n_off); + } else { + vlan_tci = rte_pktmbuf_mtod_offset(m, void *, + word5.vlan_tci_1_off); + } + + m->vlan_tci = rte_be_to_cpu_16(*vlan_tci); } + /* RSS / FDIR information from FLC */ + dpaa2_dev_rx_flc_parse(m, fd); + if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; m->ol_flags |= dpaa2_timestamp_rx_dynflag; + DPAA2_PMD_DP_DEBUG("pkt timestamp:0x%" PRIx64 "", - *dpaa2_timestamp_dynfield(m)); + *dpaa2_timestamp_dynfield(m)); } DPAA2_PMD_DP_DEBUG("HW frc = 0x%x\t packet type =0x%x " @@ -251,13 +325,15 @@ dpaa2_dev_rx_parse_slow(struct rte_mbuf *mbuf, } static inline uint32_t __rte_hot -dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) +dpaa2_dev_rx_parse(struct dpaa2_dev_priv *priv, + struct rte_mbuf *mbuf, void *hw_annot_addr) { - struct dpaa2_annot_hdr *annotation = - (struct dpaa2_annot_hdr *)hw_annot_addr; + struct dpaa2_annot_hdr *annotation = hw_annot_addr; DPAA2_PMD_DP_DEBUG("(fast parse) Annotation = 0x%" PRIx64 "\t", - annotation->word4); + annotation->word4); + + RTE_SET_USED(priv); if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L3CE)) mbuf->ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD; @@ -269,9 +345,6 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) else if (BIT_ISSET_AT_POS(annotation->word1, DPAA2_ETH_FAS_L4CV)) mbuf->ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD; - if (unlikely(dpaa2_print_parser_result)) - dpaa2_print_parse_result(annotation); - if (dpaa2_enable_ts[mbuf->port]) { *dpaa2_timestamp_dynfield(mbuf) = annotation->word2; mbuf->ol_flags |= dpaa2_timestamp_rx_dynflag; @@ -280,7 +353,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } /* Check detailed parsing requirement */ - if (annotation->word3 & 0x7FFFFC3FFFF) + if (unlikely(annotation->word3 & 0x7FFFFC3FFFF)) return dpaa2_dev_rx_parse_slow(mbuf, annotation); /* Return some common types from parse processing */ @@ -309,8 +382,7 @@ dpaa2_dev_rx_parse(struct rte_mbuf *mbuf, void *hw_annot_addr) } static inline struct rte_mbuf *__rte_hot -eth_sg_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_sg_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { struct qbman_sge *sgt, *sge; size_t sg_addr, fd_addr; @@ -338,12 +410,14 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, first_seg->pkt_len = DPAA2_GET_FD_LEN(fd); first_seg->nb_segs = 1; first_seg->next = NULL; - first_seg->port = port_id; - if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(first_seg, fd, hw_annot_addr); - else - first_seg->packet_type = - dpaa2_dev_rx_parse(first_seg, hw_annot_addr); + first_seg->port = priv->eth_dev->data->port_id; + if (dpaa2_svr_family == SVR_LX2160A) { + dpaa2_dev_rx_parse_new(priv, first_seg, fd, hw_annot_addr, false); + } else { + first_seg->packet_type = dpaa2_dev_rx_parse(priv, first_seg, + hw_annot_addr); + } + dpaa2_dev_rx_flc_parse(first_seg, fd); rte_mbuf_refcnt_set(first_seg, 1); #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -383,13 +457,22 @@ eth_sg_fd_to_mbuf(const struct qbman_fd *fd, } static inline struct rte_mbuf *__rte_hot -eth_fd_to_mbuf(const struct qbman_fd *fd, - int port_id) +dpaa2_eth_fd_to_mbuf(struct dpaa2_dev_priv *priv, const struct qbman_fd *fd) { void *v_addr = DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)); void *hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(v_addr, - rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + rte_dpaa2_bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); + int is_vlan = false; + + if (unlikely(dpaa2_svr_family == SVR_LX2160A && + (DPAA2_GET_FD_FRC_PARSE_SUM(fd) & + DPAA2_PKT_TYPE_VLAN))) { + mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); + rte_prefetch0(rte_pktmbuf_mtod(mbuf, void *)); + rte_prefetch0(hw_annot_addr); + is_vlan = true; + } /* need to repopulated some of the fields, * as they may have changed in last transmission @@ -399,7 +482,7 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); mbuf->data_len = DPAA2_GET_FD_LEN(fd); mbuf->pkt_len = mbuf->data_len; - mbuf->port = port_id; + mbuf->port = priv->eth_dev->data->port_id; mbuf->next = NULL; mbuf->hash.sched.color = DPAA2_GET_FD_DROPP(fd); rte_mbuf_refcnt_set(mbuf, 1); @@ -415,9 +498,10 @@ eth_fd_to_mbuf(const struct qbman_fd *fd, */ if (dpaa2_svr_family == SVR_LX2160A) - dpaa2_dev_rx_parse_new(mbuf, fd, hw_annot_addr); + dpaa2_dev_rx_parse_new(priv, mbuf, fd, hw_annot_addr, is_vlan); else - mbuf->packet_type = dpaa2_dev_rx_parse(mbuf, hw_annot_addr); + mbuf->packet_type = dpaa2_dev_rx_parse(priv, mbuf, hw_annot_addr); + dpaa2_dev_rx_flc_parse(mbuf, fd); DPAA2_PMD_DP_DEBUG("to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," "fd_off=%d fd =%" PRIx64 ", meta = %d bpid =%d, len=%d", @@ -676,6 +760,7 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) struct dpaa2_fas *fas; struct rte_mbuf *mbuf; char title[32]; + struct dpaa2_dev_priv *priv = eth_data->dev_private; if (unlikely(!DPAA2_PER_LCORE_DPIO)) { ret = dpaa2_affine_qbman_swp(); @@ -731,15 +816,16 @@ dump_err_pkts(struct dpaa2_queue *dpaa2_q) hw_annot_addr = (void *)((size_t)v_addr + DPAA2_FD_PTA_SIZE); fas = hw_annot_addr; + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg) - mbuf = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - mbuf = eth_fd_to_mbuf(fd, eth_data->port_id); + mbuf = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, mbuf, fd); - if (!dpaa2_print_parser_result) { - /** Don't print parse result twice.*/ - dpaa2_print_parse_result(hw_annot_addr); - } + dpaa2_dev_rx_print_parser_result(priv, fd, mbuf); DPAA2_PMD_ERR("Err pkt on port[%d]:", eth_data->port_id); DPAA2_PMD_ERR("FD offset: %d, FD err: %x, FAS status: %x", @@ -794,18 +880,12 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, struct qbman_pull_desc pulldesc; struct queue_storage_info_t *q_storage; struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; + struct dpaa2_dev_priv *priv = eth_data->dev_private; q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - /* the error-queue drain runs on the regular portal (DPAA2_PER_LCORE_PORTAL); - * the channel/interrupt path owns the ethrx portal, so skip it there - */ - if (!by_channel) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; - - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) - dump_err_pkts(priv->rx_err_vq); - } + if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { ret = dpaa2_affine_qbman_ethrx_swp(); @@ -911,18 +991,17 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, eth_data->port_id); -#if defined(RTE_LIBRTE_IEEE1588) - if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { - struct dpaa2_dev_priv *priv = eth_data->dev_private; + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); - priv->rx_timestamp = - *dpaa2_timestamp_dynfield(bufs[num_rx]); - } -#endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -991,7 +1070,10 @@ dpaa2_dev_process_parallel_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); qbman_swp_dqrr_consume(swp, dq); } @@ -1016,7 +1098,10 @@ dpaa2_dev_process_atomic_event(struct qbman_swp *swp __rte_unused, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); dqrr_index = qbman_get_dqrr_idx(dq); *dpaa2_seqn(ev->mbuf) = dqrr_index + 1; @@ -1043,7 +1128,10 @@ dpaa2_dev_process_ordered_event(struct qbman_swp *swp, ev->queue_id = rxq->ev.queue_id; ev->priority = rxq->ev.priority; - ev->mbuf = eth_fd_to_mbuf(fd, rxq->eth_data->port_id); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + ev->mbuf = dpaa2_eth_sg_fd_to_mbuf(rxq->eth_data->dev_private, fd); + else + ev->mbuf = dpaa2_eth_fd_to_mbuf(rxq->eth_data->dev_private, fd); *dpaa2_seqn(ev->mbuf) = DPAA2_ENQUEUE_FLAG_ORP; *dpaa2_seqn(ev->mbuf) |= qbman_result_DQ_odpid(dq) << DPAA2_EQCR_OPRID_SHIFT; @@ -1153,12 +1241,15 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, dpaa2_dev_prefetch_next_psr(dq_storage); fd = qbman_result_DQ_fd(dq_storage); + + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_annot_prefetch(fd); if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) - bufs[num_rx] = eth_sg_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_sg_fd_to_mbuf(priv, fd); else - bufs[num_rx] = eth_fd_to_mbuf(fd, - eth_data->port_id); + bufs[num_rx] = dpaa2_eth_fd_to_mbuf(priv, fd); + if (priv->psr_dynfield_offset >= 0) + dpaa2_dev_rx_parse_offset(priv, bufs[num_rx], fd); #if defined(RTE_LIBRTE_IEEE1588) if (bufs[num_rx]->ol_flags & RTE_MBUF_F_RX_IEEE1588_TMST) { @@ -1166,6 +1257,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, *dpaa2_timestamp_dynfield(bufs[num_rx]); } #endif + dpaa2_dev_rx_print_parser_result(priv, fd, bufs[num_rx]); dq_storage++; num_rx++; @@ -1316,7 +1408,7 @@ uint16_t dpaa2_dev_tx_conf(void *queue) return num_tx_conf; } - +#ifdef RTE_LIBRTE_IEEE1588 /* Configure the egress frame annotation for timestamp update */ static void enable_tx_tstamp(struct qbman_fd *fd) { @@ -1338,7 +1430,7 @@ static void enable_tx_tstamp(struct qbman_fd *fd) fd_faead->ctrl = DPAA2_ANNOT_FAEAD_A2V | DPAA2_ANNOT_FAEAD_UPDV | DPAA2_ANNOT_FAEAD_UPD; } - +#endif /* * Callback to handle sending packets through WRIOP based interface */ @@ -1619,8 +1711,12 @@ dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci, fd = qbman_result_eqresp_fd(&dpio_dev->eqresp[eqresp_ci]); /* Setting port id does not matter as we are to free the mbuf */ - m = eth_fd_to_mbuf(fd, 0); - rte_pktmbuf_free(m); + if (unlikely(DPAA2_FD_GET_FORMAT(fd) == qbman_fd_sg)) + m = dpaa2_eth_sg_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + else + m = dpaa2_eth_fd_to_mbuf(dpaa2_q->eth_data->dev_private, fd); + if (m) + rte_pktmbuf_free(m); } static void -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (9 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (3 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to identify IPv4/IPv6 fragmented packets, IPsec ESP, and GTP-U/GTP-C packets. Map the corresponding parser summary values to DPDK packet types. GTP-U and GTP-C packets are additionally marked with RTE_PTYPE_L4_UDP to reflect the UDP transport used by the outer tunnel header. Advertise the newly supported packet types through dpaa2_supported_ptypes_get(). Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 37 ++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 88ff5daba4..678a30e683 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index acf377730a..311084a1f0 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -162,6 +162,10 @@ #define DPAA2_PKT_TYPE_IPV6_EXT_GRE_IPV6_UDP_TCP \ (DPAA2_PKT_TYPE_IPV6_EXT | DPAA2_PSR_SUMMARY_GRE_IPV6_UDP_TCP) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (DPAA2_PSR_SUMMARY_IP_FRAG | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (DPAA2_PSR_SUMMARY_TCP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -178,6 +182,18 @@ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (DPAA2_PSR_SUMMARY_ICMP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (DPAA2_PSR_SUMMARY_IPSEC_ESP | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (DPAA2_PSR_SUMMARY_GTPU | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (DPAA2_PSR_SUMMARY_GTPC | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0100 #define DPAA2_PKT_TYPE_VLAN_2 0x0200 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 8518541236..ba62edd1d6 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -174,6 +174,43 @@ dpaa2_dev_rx_parse_new(struct dpaa2_dev_priv *priv, RTE_PTYPE_L3_IPV6; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_ETHER: m->packet_type = RTE_PTYPE_L2_ETHER; break; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 12/13] net/dpaa2: remove unused soft parser driver 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (10 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta ` (2 subsequent siblings) 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are also dropped from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_ethdev.h | 1 - drivers/net/dpaa2/dpaa2_flow.c | 564 +----------------------- drivers/net/dpaa2/dpaa2_parser_decode.h | 2 - drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 10 files changed, 10 insertions(+), 937 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..9e24cf3f5b 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -35,7 +35,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y @@ -50,7 +49,6 @@ sctp = Y tcp = Y udp = Y vlan = P -vxlan = Y [rte_flow actions] drop = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 5d20a96f1c..784f3cfccb 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -163,6 +163,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * eal: ``__rte_packed`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 678a30e683..a660a925cd 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3721,33 +3720,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 311084a1f0..a0b08bddf4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -668,7 +668,6 @@ int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev); int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev); void dpaa2_mtr_deinit(struct rte_eth_dev *dev); int dpaa2_mtr_ops_get(struct rte_eth_dev *dev, void *ops); -int dpaa2_soft_parser_loaded(void); void dpaa2_dev_mac_setup_stats(struct rte_eth_dev *dev); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 61a080893d..a4575e7314 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4906,26 +4378,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5135,15 +4587,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5152,16 +4600,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_parser_decode.h b/drivers/net/dpaa2/dpaa2_parser_decode.h index c57f08ae8c..807439bc9f 100644 --- a/drivers/net/dpaa2/dpaa2_parser_decode.h +++ b/drivers/net/dpaa2/dpaa2_parser_decode.h @@ -625,8 +625,6 @@ union __rte_packed_begin dpaa2_faf_h_parse_64b { #define DPAA2_VXLAN_IN_SADDR5_OFFSET \ offsetof(struct dpaa2_psr_result_parse, word8.vxlan_in_saddr5) -#define DPAA2_VXLAN_VNI_OFFSET \ - offsetof(struct dpaa2_psr_result_parse, word8.vxlan_vni[0]) #define DPAA2_VXLAN_IN_TYPE_OFFSET \ offsetof(struct dpaa2_psr_result_parse, word8.vxlan_eth_type) /* Set by SP for vxlan distribution end*/ diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..1d6f8659be 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 808dad8112..4f774f7c82 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -17,7 +17,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v9-S2 13/13] net/dpaa2: rename Rx queue flags 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (11 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-12 7:04 ` Prashant Gupta 2026-10-12 21:22 ` [PATCH v9-S2 00/13] net/dpaa2 updates Stephen Hemminger 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-12 7:04 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 5 +++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index a660a925cd..51a38c2df9 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3477,7 +3477,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3584,7 +3584,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index a0b08bddf4..17c1cb6cea 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -100,9 +100,10 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) + +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) #define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index ba62edd1d6..d6653948d8 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -921,7 +921,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, q_storage = dpaa2_q->q_storage[rte_lcore_id()]; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (unlikely(!DPAA2_PER_LCORE_ETHRX_DPIO)) { @@ -1193,7 +1193,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v9-S2 00/13] net/dpaa2 updates 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (12 preceding siblings ...) 2026-10-12 7:04 ` [PATCH v9-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-12 21:22 ` Stephen Hemminger 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta 14 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-12 21:22 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Mon, 12 Oct 2026 12:34:31 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > Changes in v9: > - Address review comments for meter and policing support. > - Add meter resource cleanup during device close. > - Add policing capability checks. > - Validate burst size ranges before hardware programming. > - Fix software/hardware state consistency on profile and policy updates. > - Use standard FDIR reporting for flow-steered packets. > - Replace global flow miss configuration with a per-device default flow > and remove the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. > - Document and gate minimum DPNI version requirement for 24-byte flow keys. > - Rework parser decode infrastructure and parser-result dumping. > - Parse additional tunnel and fragmented packet types. > - Fold parser-related fixes into the originating patches. > - Remove unused VXLAN offset helpers after soft parser removal. > - Move release note updates into the existing DPAA2 ethernet driver > entry under New Features. > - Fix coding style issues reported during review. > > Series overview: > - fix an integer overflow in the CCSR region mapping, > - set Tx confirmation on device init and support a larger burst size, > - support MPLS and PPPoE flow distribution, meter and policing, and the > flow drop action, with a per-device default flow miss action, > - identify Rx mbuf hash information by FLC and add minimum key size > support, > - restructure parser processing, parse tunnel and fragmented packet > types, remove the unused soft parser driver and rename Rx queue flags. > > Gagandeep Singh (7): > net/dpaa2: set Tx confirmation on device init > net/dpaa2: support larger burst size > net/dpaa2: support MPLS and PPPoE flow distribution > net/dpaa2: support meter and policing > net/dpaa2: support flow drop action > net/dpaa2: set default flow miss action per device > net/dpaa2: identify Rx mbuf hash information by FLC > > Hemant Agrawal (4): > net/dpaa2: fix integer overflow in CCSR region mapping > net/dpaa2: add minimum key size support > net/dpaa2: restructure dpaa2 parser processing > net/dpaa2: parse tunnel and fragmented packet types > > Jun Yang (2): > net/dpaa2: remove unused soft parser driver > net/dpaa2: rename Rx queue flags > > doc/guides/nics/dpaa2.rst | 1 + > doc/guides/nics/features/dpaa2.ini | 4 +- > doc/guides/rel_notes/release_26_11.rst | 15 +- > drivers/net/dpaa2/dpaa2_ethdev.c | 89 +- > drivers/net/dpaa2/dpaa2_ethdev.h | 218 +++- > drivers/net/dpaa2/dpaa2_flow.c | 633 +++------ > drivers/net/dpaa2/dpaa2_meter.c | 804 ++++++++++++ > drivers/net/dpaa2/dpaa2_parse_dump.h | 374 ------ > drivers/net/dpaa2/dpaa2_parser_decode.h | 1549 +++++++++++++++++++++++ > drivers/net/dpaa2/dpaa2_pmd_logs.h | 67 + > drivers/net/dpaa2/dpaa2_recycle.c | 24 +- > drivers/net/dpaa2/dpaa2_rxtx.c | 351 +++-- > drivers/net/dpaa2/dpaa2_sparser.c | 137 -- > drivers/net/dpaa2/dpaa2_sparser.h | 202 --- > drivers/net/dpaa2/dpaa2_tm.c | 16 +- > drivers/net/dpaa2/mc/dpni.c | 11 +- > drivers/net/dpaa2/mc/fsl_dpni.h | 25 +- > drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- > drivers/net/dpaa2/meson.build | 2 +- > 19 files changed, 3096 insertions(+), 1429 deletions(-) > create mode 100644 drivers/net/dpaa2/dpaa2_meter.c > delete mode 100644 drivers/net/dpaa2/dpaa2_parse_dump.h > create mode 100644 drivers/net/dpaa2/dpaa2_parser_decode.h > delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c > delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h > In general looks good but there still is this open question. Review: [PATCH v9-S2 00/13] net/dpaa2 updates Applies on top of v7-S1. v8 comments on release notes, the duplicated burst check, and 10/13 indent, naming and commit message are addressed. Two items from v8 remain. [PATCH 05/13] net/dpaa2: support meter and policing Warning: no answer yet on meter_lock. meter_create still drops the lock around dpaa2_mtr_hw_program(). If control operations can be concurrent, there is a race here; if not allowed, what is the point of meter_lock? Either hold it across check, program and insert, or drop the lock. Info: fsl_dpni.h still has the orphaned comment left behind when DPNI_POLICER_OPT_DO_NOT_RESET_COUNTERS was removed: -/** - * Do NOT reset counters generally for policer update - */ - ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v10-S2 00/11] net/dpaa2 updates 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta ` (13 preceding siblings ...) 2026-10-12 21:22 ` [PATCH v9-S2 00/13] net/dpaa2 updates Stephen Hemminger @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (11 more replies) 14 siblings, 12 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev Changes in v10: - Drop meter and policing support patch. - Drop parser processing rework patch. - Remove associated meter infrastructure and parser decode changes. - Update release notes to the existing DPAA2 New Features section. - Address review comments for per-device default flow miss action. - Document minimum DPNI version requirement for 24-byte flow keys. - Fold parser-related fixes into the remaining parser updates. - Remove unused soft parser files and related build integration. - Fix coding style issues reported during review. Series overview: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, - support the flow drop action and a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - parse tunnel and fragmented packet types, - remove the unused soft parser driver and rename Rx queue flags. Gagandeep Singh (6): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (3): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/features/dpaa2.ini | 4 +- doc/guides/rel_notes/release_26_11.rst | 13 + drivers/net/dpaa2/dpaa2_ethdev.c | 84 +--- drivers/net/dpaa2/dpaa2_ethdev.h | 36 +- drivers/net/dpaa2/dpaa2_flow.c | 633 ++++++------------------- drivers/net/dpaa2/dpaa2_recycle.c | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 60 ++- drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 -------- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 8 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 1 - 14 files changed, 327 insertions(+), 905 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v10-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (10 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, causing the mapping to fail, where the old code would have bumped len up to PAGE_SIZE. The correct mapping size must cover the region from the page-aligned start through offset + len. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) for map_len so that the mmap covers the full requested region regardless of page size. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 02/11] net/dpaa2: set Tx confirmation on device init 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta ` (9 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 03/11] net/dpaa2: support larger burst size 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (8 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (2 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta ` (7 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 05/11] net/dpaa2: support flow drop action 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (3 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta ` (6 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 06/11] net/dpaa2: set default flow miss action per device 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (4 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (5 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global defaulting to 0 and optionally overridden via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. Replace it with a per-device default_flow field in dpaa2_dev_priv, initialised to the lowest-priority flow ID (min(fs_entries, dist_queues) - 1) at probe time, so that each device has its own independent miss-flow setting. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..1b22d134ae 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -105,6 +105,10 @@ New Features * Added the inner IP header to the RSS hash so tunneled traffic is distributed across the Rx queues. + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id now defaults to the lowest-priority + flow of the device. Users who previously redirected unmatched frames + to a specific queue via this variable must use the rte_flow API instead. * **Updated NXP ENETC4 PMD.** diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..37c671bebf 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3539,6 +3539,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MAX(RTE_MIN(priv->fs_entries, + priv->dist_queues), 1) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..07c56c0aa4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -411,6 +411,8 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..03f9193f51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (5 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta ` (4 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are stored via rte_mbuf_sched_set() for use by the scheduler. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 20 +++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 07c56c0aa4..160178d70e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 03f9193f51..b7b79929b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..62565486a7 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,23 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->ol_flags |= + RTE_MBUF_F_RX_FDIR | + RTE_MBUF_F_RX_FDIR_ID; + m->hash.fdir.hi = (tc << 16) | flow; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 08/11] net/dpaa2: add minimum key size support 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (6 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (3 subsequent siblings) 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Support for 24-byte QoS key entries is available from DPNI version 8.7 onwards. For older DPNI versions, the existing 56-byte entry size is retained to maintain compatibility. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b7b79929b4..61a080893d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4519,7 +4522,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4529,11 +4532,11 @@ dpaa2_flow_entry_size(uint16_t key_max_size) return 0; } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || + dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int @@ -4595,7 +4598,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4686,7 +4689,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4977,11 +4980,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (7 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 17:18 ` Stephen Hemminger 2026-10-14 5:43 ` [PATCH v10-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (2 subsequent siblings) 11 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to identify IPv4/IPv6 fragmented packets, IPsec ESP, and GTP-U/GTP-C packets. Map the corresponding parser summary values to DPDK packet types. GTP-U and GTP-C packets are additionally marked with RTE_PTYPE_L4_UDP to reflect the UDP transport used by the outer tunnel header. Advertise the newly supported packet types through dpaa2_supported_ptypes_get(). Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 16 ++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 37c671bebf..0c1f176291 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 160178d70e..8e1852741c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -131,6 +131,10 @@ (0x0001 | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_EXT \ (0x0001 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_FRAG \ + (0x0002 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_FRAG \ + (0x0002 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (0x000e | DPAA2_PKT_TYPE_IPV4) #define DPAA2_PKT_TYPE_IPV6_TCP \ @@ -147,6 +151,18 @@ (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0160 #define DPAA2_PKT_TYPE_VLAN_2 0x0260 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 62565486a7..7da75649e2 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -116,6 +116,42 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v10-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types 2026-10-14 5:43 ` [PATCH v10-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-14 17:18 ` Stephen Hemminger 0 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-14 17:18 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, Hemant Agrawal On Wed, 14 Oct 2026 11:13:58 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > From: Hemant Agrawal <hemant.agrawal@nxp.com> > > Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to > identify IPv4/IPv6 fragmented packets, IPsec ESP, and > GTP-U/GTP-C packets. > > Map the corresponding parser summary values to DPDK packet > types. GTP-U and GTP-C packets are additionally marked with > RTE_PTYPE_L4_UDP to reflect the UDP transport used by the > outer tunnel header. > > Advertise the newly supported packet types through > dpaa2_supported_ptypes_get(). > > Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> AI saw this is it an issue? [PATCH 09/11] net/dpaa2: parse tunnel and fragmented packet types Warning: the fragment value changed. v9 built it from DPAA2_PSR_SUMMARY_IP_FRAG, which is 1. v10 open-codes it as 2: #define DPAA2_PKT_TYPE_IPV4_FRAG \ (0x0002 | DPAA2_PKT_TYPE_IPV4) Code 1 is already DPAA2_PKT_TYPE_IPV4_EXT, so this looks like it was picked to avoid a duplicate case label rather than taken from the parser spec. If the hardware reports fragments as 1, the new FRAG cases never match and fragments keep coming up as RTE_PTYPE_L3_IPV4_EXT. Please confirm the summary code. If it is 1, drop the FRAG defines and report L4_FRAG from the existing EXT case: case DPAA2_PKT_TYPE_IPV4_EXT: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_FRAG; break; Info: ESP and GTP values are now bare numbers (0x0005, 0x0014, 0x0015). Name them, as v9 did, so the next reader can check them against the parser summary table. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v10-S2 10/11] net/dpaa2: remove unused soft parser driver 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (8 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-14 5:43 ` Prashant Gupta 2026-10-14 5:44 ` [PATCH v10-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:43 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are also dropped from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_flow.c | 564 +------------------------ drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 8 files changed, 10 insertions(+), 934 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..9e24cf3f5b 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -35,7 +35,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y @@ -50,7 +49,6 @@ sctp = Y tcp = Y udp = Y vlan = P -vxlan = Y [rte_flow actions] drop = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 1b22d134ae..3635507bbe 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -163,6 +163,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * eal: ``__rte_packed`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0c1f176291..4f5e738965 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3718,33 +3717,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 61a080893d..a4575e7314 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4906,26 +4378,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5135,15 +4587,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5152,16 +4600,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..1d6f8659be 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..b821f7bfad 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -16,7 +16,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v10-S2 11/11] net/dpaa2: rename Rx queue flags 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (9 preceding siblings ...) 2026-10-14 5:43 ` [PATCH v10-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-14 5:44 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta 11 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-14 5:44 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 6 ++++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 4f5e738965..b3a1631923 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3475,7 +3475,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3581,7 +3581,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 8e1852741c..23de2a7262 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -98,9 +98,11 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) + +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 7da75649e2..85c8a4550b 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -839,7 +839,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (!by_channel) { struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); } @@ -1104,7 +1104,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 00/11] net/dpaa2 updates 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta ` (10 preceding siblings ...) 2026-10-14 5:44 ` [PATCH v10-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (12 more replies) 11 siblings, 13 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev Changes in v11: - Fix fragmented packet type handling to match hardware parser summary reporting. - Address review comments. Series overview: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, - support the flow drop action and a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - parse tunnel and fragmented packet types, - remove the unused soft parser driver and rename Rx queue flags. Gagandeep Singh (6): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (3): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/features/dpaa2.ini | 4 +- doc/guides/rel_notes/release_26_11.rst | 13 + drivers/net/dpaa2/dpaa2_ethdev.c | 84 +--- drivers/net/dpaa2/dpaa2_ethdev.h | 32 +- drivers/net/dpaa2/dpaa2_flow.c | 633 ++++++------------------- drivers/net/dpaa2/dpaa2_recycle.c | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 56 ++- drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 -------- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 8 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 1 - 14 files changed, 317 insertions(+), 907 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v11-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (11 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, causing the mapping to fail, where the old code would have bumped len up to PAGE_SIZE. The correct mapping size must cover the region from the page-aligned start through offset + len. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) for map_len so that the mmap covers the full requested region regardless of page size. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 02/11] net/dpaa2: set Tx confirmation on device init 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta ` (10 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 03/11] net/dpaa2: support larger burst size 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (9 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (2 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta ` (8 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 05/11] net/dpaa2: support flow drop action 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (3 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta ` (7 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 06/11] net/dpaa2: set default flow miss action per device 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (4 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (6 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global defaulting to 0 and optionally overridden via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. Replace it with a per-device default_flow field in dpaa2_dev_priv, initialised to the lowest-priority flow ID (min(fs_entries, dist_queues) - 1) at probe time, so that each device has its own independent miss-flow setting. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..1b22d134ae 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -105,6 +105,10 @@ New Features * Added the inner IP header to the RSS hash so tunneled traffic is distributed across the Rx queues. + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id now defaults to the lowest-priority + flow of the device. Users who previously redirected unmatched frames + to a specific queue via this variable must use the rte_flow API instead. * **Updated NXP ENETC4 PMD.** diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..37c671bebf 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3539,6 +3539,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MAX(RTE_MIN(priv->fs_entries, + priv->dist_queues), 1) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..07c56c0aa4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -411,6 +411,8 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..03f9193f51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (5 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta ` (5 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are stored via rte_mbuf_sched_set() for use by the scheduler. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 20 +++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 07c56c0aa4..160178d70e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 03f9193f51..b7b79929b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..62565486a7 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,23 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->ol_flags |= + RTE_MBUF_F_RX_FDIR | + RTE_MBUF_F_RX_FDIR_ID; + m->hash.fdir.hi = (tc << 16) | flow; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 08/11] net/dpaa2: add minimum key size support 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (6 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (4 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Support for 24-byte QoS key entries is available from DPNI version 8.7 onwards. For older DPNI versions, the existing 56-byte entry size is retained to maintain compatibility. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b7b79929b4..61a080893d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4519,7 +4522,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4529,11 +4532,11 @@ dpaa2_flow_entry_size(uint16_t key_max_size) return 0; } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || + dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int @@ -4595,7 +4598,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4686,7 +4689,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4977,11 +4980,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (7 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (3 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to identify IPv4/IPv6 fragmented packets, IPsec ESP, and GTP-U/GTP-C packets. Map the corresponding parser summary values to DPDK packet types. GTP-U and GTP-C packets are additionally marked with RTE_PTYPE_L4_UDP to reflect the UDP transport used by the outer tunnel header. Advertise the newly supported packet types through dpaa2_supported_ptypes_get(). Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 12 ++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 37c671bebf..0c1f176291 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 160178d70e..c68e24cbb8 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -147,6 +147,18 @@ (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0160 #define DPAA2_PKT_TYPE_VLAN_2 0x0260 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 62565486a7..052133eb55 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -78,11 +78,11 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, break; case DPAA2_PKT_TYPE_IPV4_EXT: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_FRAG; break; case DPAA2_PKT_TYPE_IPV6_EXT: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_FRAG; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | @@ -116,6 +116,34 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v11-S2 10/11] net/dpaa2: remove unused soft parser driver 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (8 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 23:36 ` Stephen Hemminger 2026-10-15 9:25 ` [PATCH v11-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta ` (2 subsequent siblings) 12 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are also dropped from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_flow.c | 564 +------------------------ drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 8 files changed, 10 insertions(+), 934 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..9e24cf3f5b 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -35,7 +35,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y @@ -50,7 +49,6 @@ sctp = Y tcp = Y udp = Y vlan = P -vxlan = Y [rte_flow actions] drop = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 1b22d134ae..3635507bbe 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -163,6 +163,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * eal: ``__rte_packed`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0c1f176291..4f5e738965 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3718,33 +3717,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 61a080893d..a4575e7314 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4906,26 +4378,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5135,15 +4587,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5152,16 +4600,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..1d6f8659be 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..b821f7bfad 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -16,7 +16,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v11-S2 10/11] net/dpaa2: remove unused soft parser driver 2026-10-15 9:25 ` [PATCH v11-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-15 23:36 ` Stephen Hemminger 0 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-15 23:36 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, Jun Yang On Thu, 15 Oct 2026 14:55:12 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > From: Jun Yang <jun.yang@nxp.com> > > The DPAA2 soft parser (SP) byte code has to be installed by the boot > firmware before Linux starts; the WRIOP parser cannot be reprogrammed once > the MC is up. Loading an SP image at run time from the PMD therefore never > took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead > code and are removed. > > The rte_flow VXLAN and eCPRI pattern items were only ever accepted while > an SP image was believed to be loaded. With the SP gone they are rejected > by dpaa2_dev_verify_patterns() before the configure switch is reached, so > their handlers dpaa2_configure_flow_vxlan() and > dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask > descriptors and the VXLAN_HF_VNI helper are removed as well. Both items are > also dropped from the dpaa2 feature matrix so that the documented > capabilities match the code. > > Signed-off-by: Jun Yang <jun.yang@nxp.com> > Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> > --- After applying this to next-net, I reran the set of checks. But this patch causes problem: $ ./devtools/check-doc-vs-code.sh rte_flow doc out of sync for dpaa2 item vxlan Backed out the whole series, update and resend. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v11-S2 11/11] net/dpaa2: rename Rx queue flags 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (9 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-15 9:25 ` Prashant Gupta 2026-10-15 23:26 ` [PATCH v11-S2 00/11] net/dpaa2 updates Stephen Hemminger 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-15 9:25 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 6 ++++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 4f5e738965..b3a1631923 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3475,7 +3475,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3581,7 +3581,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c68e24cbb8..5e3f8f2f78 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -98,9 +98,11 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) + +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 052133eb55..e83fa8c158 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -831,7 +831,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (!by_channel) { struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); } @@ -1096,7 +1096,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v11-S2 00/11] net/dpaa2 updates 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (10 preceding siblings ...) 2026-10-15 9:25 ` [PATCH v11-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-15 23:26 ` Stephen Hemminger 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta 12 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-15 23:26 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 15 Oct 2026 14:55:02 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > Changes in v11: > - Fix fragmented packet type handling to match hardware parser > summary reporting. > - Address review comments. > > Series overview: > - fix an integer overflow in the CCSR region mapping, > - set Tx confirmation on device init and support a larger burst size, > - support MPLS and PPPoE flow distribution, > - support the flow drop action and a per-device default flow miss action, > - identify Rx mbuf hash information by FLC and add minimum key size > support, > - parse tunnel and fragmented packet types, > - remove the unused soft parser driver and rename Rx queue flags. Applied to next-net ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v12-S2 00/11] net/dpaa2 updates 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta ` (11 preceding siblings ...) 2026-10-15 23:26 ` [PATCH v11-S2 00/11] net/dpaa2 updates Stephen Hemminger @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (12 more replies) 12 siblings, 13 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev Changes in v12: - Restore VXLAN rte_flow item documentation in dpaa2.ini to keep documentation aligned with PMD capabilities. - Fix documentation check failure reported after application to next-net. Series overview: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, - support the flow drop action and a per-device default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - parse tunnel and fragmented packet types, - remove the unused soft parser driver and rename Rx queue flags. Gagandeep Singh (6): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (3): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: parse tunnel and fragmented packet types Jun Yang (2): net/dpaa2: remove unused soft parser driver net/dpaa2: rename Rx queue flags doc/guides/nics/features/dpaa2.ini | 3 +- doc/guides/rel_notes/release_26_11.rst | 13 + drivers/net/dpaa2/dpaa2_ethdev.c | 84 +--- drivers/net/dpaa2/dpaa2_ethdev.h | 32 +- drivers/net/dpaa2/dpaa2_flow.c | 633 ++++++------------------- drivers/net/dpaa2/dpaa2_recycle.c | 24 +- drivers/net/dpaa2/dpaa2_rxtx.c | 56 ++- drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 -------- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 8 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- drivers/net/dpaa2/meson.build | 1 - 14 files changed, 317 insertions(+), 906 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v12-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (11 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region, PAGE_SIZE is a macro defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and passed to mmap, causing an integer overflow (Coverity CID 49765682). The old round-down "len & PAGE_MASK" ignored the in-page offset: for a 4096-byte or 6656-byte len on a 64K-page kernel the masked result is 0, causing the mapping to fail, where the old code would have bumped len up to PAGE_SIZE. The correct mapping size must cover the region from the page-aligned start through offset + len. Fix by calling sysconf(_SC_PAGESIZE) explicitly into a signed long, checking for a non-positive return before use, computing page_mask from the verified value, and using RTE_ALIGN_CEIL(offset + len, page_size) for map_len so that the mmap covers the full requested region regardless of page size. The page-aligned start address and the back-pointer offset are both derived from the same page_mask, keeping the three values consistent. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 02/11] net/dpaa2: set Tx confirmation on device init 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta ` (10 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 03/11] net/dpaa2: support larger burst size 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (9 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (2 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta ` (8 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 05/11] net/dpaa2: support flow drop action 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (3 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta ` (7 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 06/11] net/dpaa2: set default flow miss action per device 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (4 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (6 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> The flow steering miss flow id was a file-scope global defaulting to 0 and optionally overridden via the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable. Replace it with a per-device default_flow field in dpaa2_dev_priv, initialised to the lowest-priority flow ID (min(fs_entries, dist_queues) - 1) at probe time, so that each device has its own independent miss-flow setting. The DPAA2_FLOW_CONTROL_MISS_FLOW environment variable is removed. Users who relied on it must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.c | 2 ++ drivers/net/dpaa2/dpaa2_ethdev.h | 2 ++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..1b22d134ae 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -105,6 +105,10 @@ New Features * Added the inner IP header to the RSS hash so tunneled traffic is distributed across the Rx queues. + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id now defaults to the lowest-priority + flow of the device. Users who previously redirected unmatched frames + to a specific queue via this variable must use the rte_flow API instead. * **Updated NXP ENETC4 PMD.** diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..37c671bebf 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -3539,6 +3539,8 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) priv->dist_queues = attr.num_queues; priv->num_channels = attr.num_channels; priv->channel_inuse = 0; + priv->default_flow = RTE_MAX(RTE_MIN(priv->fs_entries, + priv->dist_queues), 1) - 1; rte_spinlock_init(&priv->lpbk_qp_lock); /* only if the custom CG is enabled */ diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..07c56c0aa4 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -411,6 +411,8 @@ struct dpaa2_dev_priv { uint8_t en_loose_ordered; uint8_t max_cgs; uint8_t cgid_in_use[MAX_RX_QUEUES]; + /* Lowest priority FS flow id to receive flow steering miss frames. */ + uint16_t default_flow; /* Current hash distribution size per RX TC, written by * dpaa2_setup_flow_dist_size() and read by reta_query / reta_update. diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..03f9193f51 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = priv->default_flow; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (5 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta ` (5 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure the flow steering action with FLC enabled to align the stashing setting with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are stored via rte_mbuf_sched_set() for use by the scheduler. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 20 +++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 07c56c0aa4..160178d70e 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 03f9193f51..b7b79929b4 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..62565486a7 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,23 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->ol_flags |= + RTE_MBUF_F_RX_FDIR | + RTE_MBUF_F_RX_FDIR_ID; + m->hash.fdir.hi = (tc << 16) | flow; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 08/11] net/dpaa2: add minimum key size support 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (6 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (4 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Support for 24-byte QoS key entries is available from DPNI version 8.7 onwards. For older DPNI versions, the existing 56-byte entry size is retained to maintain compatibility. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index b7b79929b4..61a080893d 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4519,7 +4522,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4529,11 +4532,11 @@ dpaa2_flow_entry_size(uint16_t key_max_size) return 0; } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || + dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int @@ -4595,7 +4598,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4686,7 +4689,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4977,11 +4980,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (7 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta ` (3 subsequent siblings) 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to identify IPv4/IPv6 fragmented packets, IPsec ESP, and GTP-U/GTP-C packets. Map the corresponding parser summary values to DPDK packet types. GTP-U and GTP-C packets are additionally marked with RTE_PTYPE_L4_UDP to reflect the UDP transport used by the outer tunnel header. Advertise the newly supported packet types through dpaa2_supported_ptypes_get(). Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 ++++ drivers/net/dpaa2/dpaa2_ethdev.h | 12 ++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 37c671bebf..0c1f176291 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 160178d70e..c68e24cbb8 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -147,6 +147,18 @@ (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) #define DPAA2_PKT_TYPE_IPV6_ICMP \ (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0160 #define DPAA2_PKT_TYPE_VLAN_2 0x0260 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 62565486a7..052133eb55 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -78,11 +78,11 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, break; case DPAA2_PKT_TYPE_IPV4_EXT: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; + RTE_PTYPE_L3_IPV4_EXT | RTE_PTYPE_L4_FRAG; break; case DPAA2_PKT_TYPE_IPV6_EXT: m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; + RTE_PTYPE_L3_IPV6_EXT | RTE_PTYPE_L4_FRAG; break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | @@ -116,6 +116,34 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v12-S2 10/11] net/dpaa2: remove unused soft parser driver 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (8 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-20 13:45 ` Stephen Hemminger 2026-10-16 7:03 ` [PATCH v12-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta ` (2 subsequent siblings) 12 siblings, 1 reply; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> The DPAA2 soft parser (SP) byte code has to be installed by the boot firmware before Linux starts; the WRIOP parser cannot be reprogrammed once the MC is up. Loading an SP image at run time from the PMD therefore never took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead code and are removed. The rte_flow VXLAN and eCPRI pattern items were only ever accepted while an SP image was believed to be loaded. With the SP gone they are rejected by dpaa2_dev_verify_patterns() before the configure switch is reached, so their handlers dpaa2_configure_flow_vxlan() and dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask descriptors and the VXLAN_HF_VNI helper are removed as well. The eCPRI item is also removed from the dpaa2 feature matrix so that the documented capabilities match the code. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 1 - doc/guides/rel_notes/release_26_11.rst | 9 + drivers/net/dpaa2/dpaa2_ethdev.c | 28 -- drivers/net/dpaa2/dpaa2_flow.c | 564 +------------------------ drivers/net/dpaa2/dpaa2_recycle.c | 1 - drivers/net/dpaa2/dpaa2_sparser.c | 137 ------ drivers/net/dpaa2/dpaa2_sparser.h | 202 --------- drivers/net/dpaa2/meson.build | 1 - 8 files changed, 10 insertions(+), 933 deletions(-) delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.c delete mode 100644 drivers/net/dpaa2/dpaa2_sparser.h diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 49faebcd06..2060a5bcd2 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -35,7 +35,6 @@ Usage doc = Y [rte_flow items] ah = Y -ecpri = Y esp = Y eth = P gre = Y diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 1b22d134ae..3635507bbe 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -163,6 +163,15 @@ Removed Items Also, make sure to start the actual text at the margin. ======================================================= +* **Removed soft parser support from the dpaa2 net driver.** + + The DPAA2 soft parser (SP) blob has to be loaded by the boot firmware + before Linux starts, so loading it at run time from the PMD never took + effect. The unused SP loader has been removed, together with the rte_flow + VXLAN and eCPRI pattern items that were only accepted while an SP image + was believed to be loaded. Those two items are no longer advertised in + the dpaa2 feature matrix. + * Removed deprecated symbols: * eal: ``__rte_packed`` diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 0c1f176291..4f5e738965 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -29,7 +29,6 @@ #include <mc/fsl_dpmng.h> #include <mc/fsl_dpcon.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #define DRIVER_LOOPBACK_MODE "drv_loopback" @@ -3718,33 +3717,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } eth_dev->data->mtu = RTE_ETHER_MTU; - /*TODO To enable soft parser support DPAA2 driver needs to integrate - * with external entity to receive byte code for software sequence - * and same will be offload to the H/W using MC interface. - * Currently it is assumed that DPAA2 driver has byte code by some - * mean and same if offloaded to H/W. - */ - if (getenv("DPAA2_ENABLE_SOFT_PARSER")) { - WRIOP_SS_INITIALIZER(priv); - ret = dpaa2_eth_load_wriop_soft_parser(priv, DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in loading softparser", - ret); - goto init_err; - } - - ret = dpaa2_eth_enable_wriop_soft_parser(priv, - DPNI_SS_INGRESS); - if (ret < 0) { - DPAA2_PMD_ERR(" Error(%d) in enabling softparser", - ret); - goto init_err; - } - } - - ret = dpaa2_soft_parser_loaded(); - if (ret > 0) - DPAA2_PMD_INFO("soft parser is loaded"); DPAA2_PMD_INFO("%s: netdev created, connected to %s", eth_dev->data->name, dpaa2_dev->ep_name); diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 61a080893d..a4575e7314 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static int dpaa2_sp_loaded = -1; /* Default size of a key */ #define DPNI_DEFAULT_KEY_SIZE 24 @@ -42,7 +41,6 @@ enum dpaa2_flow_dist_type { #define DPAA2_FLOW_RAW_OFFSET_FIELD_SHIFT 16 #define DPAA2_FLOW_MAX_KEY_SIZE 16 #define DPAA2_PROT_FIELD_STRING_SIZE 16 -#define VXLAN_HF_VNI 0x08 struct dpaa2_dev_flow { LIST_ENTRY(dpaa2_dev_flow) next; @@ -87,12 +85,6 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_RAW }; -static const -enum rte_flow_item_type dpaa2_sp_supported_pattern_type[] = { - RTE_FLOW_ITEM_TYPE_VXLAN, - RTE_FLOW_ITEM_TYPE_ECPRI -}; - static const enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_END, @@ -169,18 +161,6 @@ static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = { .protocol = RTE_BE16(0xffff), }; -static const struct rte_flow_item_vxlan dpaa2_flow_item_vxlan_mask = { - .flags = 0xff, - .vni = { 0xff, 0xff, 0xff }, -}; - -static const struct rte_flow_item_ecpri dpaa2_flow_item_ecpri_mask = { - .hdr.common.type = 0xff, - .hdr.dummy[0] = RTE_BE32(0xffffffff), - .hdr.dummy[1] = RTE_BE32(0xffffffff), - .hdr.dummy[2] = RTE_BE32(0xffffffff), -}; - static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; @@ -434,92 +414,6 @@ dpaa2_flow_fs_entry_log(const char *log_info, DPAA2_FLOW_DUMP("\r\n"); } -/** For LX2160A, LS2088A and LS1088A*/ -#define WRIOP_CCSR_BASE 0x8b80000 -#define WRIOP_CCSR_CTLU_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_OFFSET 0 -#define WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET 0 - -#define WRIOP_INGRESS_PARSER_PHY \ - (WRIOP_CCSR_BASE + WRIOP_CCSR_CTLU_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_OFFSET + \ - WRIOP_CCSR_CTLU_PARSER_INGRESS_OFFSET) - -struct dpaa2_parser_ccsr { - uint32_t psr_cfg; - uint32_t psr_idle; - uint32_t psr_pclm; - uint8_t psr_ver_min; - uint8_t psr_ver_maj; - uint8_t psr_id1_l; - uint8_t psr_id1_h; - uint32_t psr_rev2; - uint8_t rsv[0x2c]; - uint8_t sp_ins[4032]; -}; - -int -dpaa2_soft_parser_loaded(void) -{ - int fd, i, ret = 0; - struct dpaa2_parser_ccsr *parser_ccsr = NULL; - - dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - - if (dpaa2_sp_loaded >= 0) - return dpaa2_sp_loaded; - - fd = open("/dev/mem", O_RDWR | O_SYNC); - if (fd < 0) { - DPAA2_PMD_ERR("open \"/dev/mem\" ERROR(%d)", fd); - ret = fd; - goto exit; - } - - parser_ccsr = mmap(NULL, sizeof(struct dpaa2_parser_ccsr), - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - WRIOP_INGRESS_PARSER_PHY); - if (!parser_ccsr) { - DPAA2_PMD_ERR("Map 0x%" PRIx64 "(size=0x%x) failed", - (uint64_t)WRIOP_INGRESS_PARSER_PHY, - (uint32_t)sizeof(struct dpaa2_parser_ccsr)); - ret = -ENOBUFS; - goto exit; - } - - DPAA2_PMD_INFO("Parser ID:0x%02x%02x, Rev:major(%02x), minor(%02x)", - parser_ccsr->psr_id1_h, parser_ccsr->psr_id1_l, - parser_ccsr->psr_ver_maj, parser_ccsr->psr_ver_min); - - if (dpaa2_flow_control_log) { - for (i = 0; i < 64; i++) { - DPAA2_FLOW_DUMP("%02x ", - parser_ccsr->sp_ins[i]); - if (!((i + 1) % 16)) - DPAA2_FLOW_DUMP("\r\n"); - } - } - - for (i = 0; i < 16; i++) { - if (parser_ccsr->sp_ins[i]) { - dpaa2_sp_loaded = 1; - break; - } - } - if (dpaa2_sp_loaded < 0) - dpaa2_sp_loaded = 0; - - ret = dpaa2_sp_loaded; - -exit: - if (parser_ccsr) - munmap(parser_ccsr, sizeof(struct dpaa2_parser_ccsr)); - if (fd >= 0) - close(fd); - - return ret; -} - static int dpaa2_flow_ip_address_extract(enum net_prot prot, uint32_t field) @@ -1766,13 +1660,7 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gre_mask; size = sizeof(struct rte_flow_item_gre); break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - mask_support = (const char *)&dpaa2_flow_item_vxlan_mask; - size = sizeof(struct rte_flow_item_vxlan); break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - mask_support = (const char *)&dpaa2_flow_item_ecpri_mask; - size = sizeof(struct rte_flow_item_ecpri); break; case RTE_FLOW_ITEM_TYPE_GTP: mask_support = (const char *)&dpaa2_flow_item_gtp_mask; @@ -3568,422 +3456,6 @@ dpaa2_configure_flow_gre(struct dpaa2_dev_flow *flow, return 0; } -static int -dpaa2_configure_flow_vxlan(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_vxlan *spec, *mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = &dpaa2_pattern->generic_item; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - mask = pattern->mask ? - pattern->mask : &dpaa2_flow_item_vxlan_mask; - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-VXLAN distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAF_VXLAN_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_VXLAN); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of VXLAN not support."); - - return ret; - } - - if (mask->flags) { - if (spec->flags != VXLAN_HF_VNI) { - DPAA2_PMD_ERR("vxlan flag(0x%02x) must be 0x%02x.", - spec->flags, VXLAN_HF_VNI); - return -EINVAL; - } - if (mask->flags != 0xff) { - DPAA2_PMD_ERR("Not support to extract vxlan flag."); - return -EINVAL; - } - } - - if (mask->vni[0] || mask->vni[1] || mask->vni[2]) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - DPAA2_VXLAN_VNI_OFFSET, - sizeof(mask->vni), spec->vni, - mask->vni, - priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - -static int -dpaa2_configure_flow_ecpri(struct dpaa2_dev_flow *flow, - struct rte_eth_dev *dev, - const struct rte_flow_attr *attr, - const struct rte_dpaa2_flow_item *dpaa2_pattern, - const struct rte_flow_action actions[] __rte_unused, - struct rte_flow_error *error __rte_unused, - int *device_configured) -{ - int ret, local_cfg = 0; - uint32_t group; - const struct rte_flow_item_ecpri *spec, *mask; - struct rte_flow_item_ecpri local_mask; - struct dpaa2_dev_priv *priv = dev->data->dev_private; - const struct rte_flow_item *pattern = - &dpaa2_pattern->generic_item; - uint8_t extract_nb = 0, i; - uint64_t rule_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint64_t mask_data[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_size[DPAA2_ECPRI_MAX_EXTRACT_NB]; - uint8_t extract_off[DPAA2_ECPRI_MAX_EXTRACT_NB]; - - group = attr->group; - - /* Parse pattern list to get the matching parameters */ - spec = pattern->spec; - if (pattern->mask) { - memcpy(&local_mask, pattern->mask, - sizeof(struct rte_flow_item_ecpri)); - local_mask.hdr.common.u32 = - rte_be_to_cpu_32(local_mask.hdr.common.u32); - mask = &local_mask; - } else { - mask = &dpaa2_flow_item_ecpri_mask; - } - - /* Get traffic class index and flow id to be configured */ - flow->tc_id = group; - flow->tc_index = attr->priority; - - if (dpaa2_pattern->in_tunnel) { - DPAA2_PMD_ERR("Tunnel-ECPRI distribution not support"); - return -ENOTSUP; - } - - if (!spec) { - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_QOS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - ret = dpaa2_flow_identify_by_faf(priv, flow, - FAFE_ECPRI_FRAM, DPAA2_FLOW_FS_TYPE, - group, &local_cfg); - if (ret) - return ret; - - (*device_configured) |= local_cfg; - return 0; - } - - ret = dpaa2_flow_extract_support((const uint8_t *)mask, - RTE_FLOW_ITEM_TYPE_ECPRI); - if (ret) { - DPAA2_PMD_WARN("Extract field(s) of ECPRI not support."); - - return ret; - } - - if (mask->hdr.common.type != 0xff) { - DPAA2_PMD_WARN("ECPRI header type not specified."); - - return -EINVAL; - } - - if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_IQ_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_0; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type0.pc_id) { - rule_data[extract_nb] = spec->hdr.type0.pc_id; - mask_data[extract_nb] = mask->hdr.type0.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, pc_id); - extract_nb++; - } - if (mask->hdr.type0.seq_id) { - rule_data[extract_nb] = spec->hdr.type0.seq_id; - mask_data[extract_nb] = mask->hdr.type0.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_iq_data, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_BIT_SEQ) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_1; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type1.pc_id) { - rule_data[extract_nb] = spec->hdr.type1.pc_id; - mask_data[extract_nb] = mask->hdr.type1.pc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, pc_id); - extract_nb++; - } - if (mask->hdr.type1.seq_id) { - rule_data[extract_nb] = spec->hdr.type1.seq_id; - mask_data[extract_nb] = mask->hdr.type1.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_bit_seq, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RTC_CTRL) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_2; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type2.rtc_id) { - rule_data[extract_nb] = spec->hdr.type2.rtc_id; - mask_data[extract_nb] = mask->hdr.type2.rtc_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, rtc_id); - extract_nb++; - } - if (mask->hdr.type2.seq_id) { - rule_data[extract_nb] = spec->hdr.type2.seq_id; - mask_data[extract_nb] = mask->hdr.type2.seq_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_rtc_ctrl, seq_id); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_GEN_DATA) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_3; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type3.pc_id || mask->hdr.type3.seq_id) - DPAA2_PMD_WARN("Extract type3 msg not support."); - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RM_ACC) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_4; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type4.rma_id) { - rule_data[extract_nb] = spec->hdr.type4.rma_id; - mask_data[extract_nb] = mask->hdr.type4.rma_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 0; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * rma_id); - */ - extract_nb++; - } - if (mask->hdr.type4.ele_id) { - rule_data[extract_nb] = spec->hdr.type4.ele_id; - mask_data[extract_nb] = mask->hdr.type4.ele_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + 2; - /** Compiler not support to take address - * of bit-field - * offsetof(struct rte_ecpri_msg_rm_access, - * ele_id); - */ - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_DLY_MSR) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_5; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type5.msr_id) { - rule_data[extract_nb] = spec->hdr.type5.msr_id; - mask_data[extract_nb] = mask->hdr.type5.msr_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - msr_id); - extract_nb++; - } - if (mask->hdr.type5.act_type) { - rule_data[extract_nb] = spec->hdr.type5.act_type; - mask_data[extract_nb] = mask->hdr.type5.act_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_delay_measure, - act_type); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_RMT_RST) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_6; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type6.rst_id) { - rule_data[extract_nb] = spec->hdr.type6.rst_id; - mask_data[extract_nb] = mask->hdr.type6.rst_id; - extract_size[extract_nb] = sizeof(rte_be16_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_id); - extract_nb++; - } - if (mask->hdr.type6.rst_op) { - rule_data[extract_nb] = spec->hdr.type6.rst_op; - mask_data[extract_nb] = mask->hdr.type6.rst_op; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_remote_reset, - rst_op); - extract_nb++; - } - } else if (spec->hdr.common.type == RTE_ECPRI_MSG_TYPE_EVT_IND) { - rule_data[extract_nb] = ECPRI_FAFE_TYPE_7; - mask_data[extract_nb] = 0xff; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = DPAA2_FAFE_PSR_OFFSET; - extract_nb++; - - if (mask->hdr.type7.evt_id) { - rule_data[extract_nb] = spec->hdr.type7.evt_id; - mask_data[extract_nb] = mask->hdr.type7.evt_id; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_id); - extract_nb++; - } - if (mask->hdr.type7.evt_type) { - rule_data[extract_nb] = spec->hdr.type7.evt_type; - mask_data[extract_nb] = mask->hdr.type7.evt_type; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - evt_type); - extract_nb++; - } - if (mask->hdr.type7.seq) { - rule_data[extract_nb] = spec->hdr.type7.seq; - mask_data[extract_nb] = mask->hdr.type7.seq; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - seq); - extract_nb++; - } - if (mask->hdr.type7.number) { - rule_data[extract_nb] = spec->hdr.type7.number; - mask_data[extract_nb] = mask->hdr.type7.number; - extract_size[extract_nb] = sizeof(uint8_t); - extract_off[extract_nb] = - DPAA2_ECPRI_MSG_OFFSET + - offsetof(struct rte_ecpri_msg_event_ind, - number); - extract_nb++; - } - } else { - DPAA2_PMD_ERR("Invalid ecpri header type(%d)", - spec->hdr.common.type); - return -EINVAL; - } - - for (i = 0; i < extract_nb; i++) { - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_QOS_TYPE); - if (ret) - return ret; - - ret = dpaa2_flow_add_pr_extract_rule(flow, - extract_off[i], - extract_size[i], &rule_data[i], &mask_data[i], - priv, group, - device_configured, - DPAA2_FLOW_FS_TYPE); - if (ret) - return ret; - } - - (*device_configured) |= local_cfg; - - return 0; -} - static int dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4906,26 +4378,6 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; - case RTE_FLOW_ITEM_TYPE_VXLAN: - ret = dpaa2_configure_flow_vxlan(flow, dev, attr, - &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("VXLAN flow config failed!"); - goto end_flow_set; - } - break; - case RTE_FLOW_ITEM_TYPE_ECPRI: - ret = dpaa2_configure_flow_ecpri(flow, - dev, attr, &dpaa2_pattern[i], - actions, error, - &is_keycfg_configured); - if (ret) { - DPAA2_PMD_ERR("ECPRI flow config failed!"); - goto end_flow_set; - } - break; case RTE_FLOW_ITEM_TYPE_GTP: ret = dpaa2_configure_flow_gtp(flow, dev, attr, &dpaa2_pattern[i], @@ -5135,15 +4587,11 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) unsigned int i, j, is_found = 0; int ret = 0; const enum rte_flow_item_type *hp_supported; - const enum rte_flow_item_type *sp_supported; - uint64_t hp_supported_num, sp_supported_num; + uint64_t hp_supported_num; hp_supported = dpaa2_hp_supported_pattern_type; hp_supported_num = RTE_DIM(dpaa2_hp_supported_pattern_type); - sp_supported = dpaa2_sp_supported_pattern_type; - sp_supported_num = RTE_DIM(dpaa2_sp_supported_pattern_type); - for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) { is_found = 0; for (i = 0; i < hp_supported_num; i++) { @@ -5152,16 +4600,6 @@ dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[]) break; } } - if (is_found) - continue; - if (dpaa2_sp_loaded > 0) { - for (i = 0; i < sp_supported_num; i++) { - if (sp_supported[i] == pattern[j].type) { - is_found = 1; - break; - } - } - } if (!is_found) { DPAA2_PMD_WARN("Flow type(%d) not supported", pattern[j].type); diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index 9b6ae3f515..1d6f8659be 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -23,7 +23,6 @@ #include <dpaa2_hw_dpio.h> #include <mc/fsl_dpmng.h> #include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" #include <fsl_qbman_debug.h> #include <rte_io.h> diff --git a/drivers/net/dpaa2/dpaa2_sparser.c b/drivers/net/dpaa2/dpaa2_sparser.c deleted file mode 100644 index 6c3e6eb573..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2023 NXP - */ - -#include <rte_mbuf.h> -#include <rte_ethdev.h> -#include <rte_malloc.h> -#include <rte_memcpy.h> -#include <rte_string_fns.h> -#include <dev_driver.h> - -#include <fslmc_logs.h> -#include <fslmc_vfio.h> -#include <dpaa2_hw_pvt.h> -#include <dpaa2_hw_dpio.h> -#include <dpaa2_hw_mempool.h> -#include <dpaa2_pmd_logs.h> - -#include "dpaa2_ethdev.h" -#include "dpaa2_sparser.h" -#include "base/dpaa2_hw_dpni_annot.h" -#define __STDC_FORMAT_MACROS -#include <stdint.h> -#include <inttypes.h> - -static uint8_t wriop_bytecode[] = { - 0x00, 0x04, 0x29, 0x42, 0x03, 0xe0, 0x12, 0x00, 0x29, 0x02, - 0x18, 0x00, 0x87, 0x3c, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00 -}; - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_load_ss_cfg cfg; - struct dpni_drv_sparser_param sp_param; - uint8_t *addr; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - sp_param.start_pc = priv->ss_offset; - sp_param.byte_code = &wriop_bytecode[0]; - sp_param.size = sizeof(wriop_bytecode); - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.ss_size = sp_param.size; - - addr = rte_malloc(NULL, sp_param.size, 64); - if (!addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(addr, sp_param.byte_code, sp_param.size); - cfg.ss_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(addr, sp_param.size); - if (cfg.ss_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("No IOMMU map for soft sequence(%p), size=%d", - addr, sp_param.size); - rte_free(addr); - - return -ENOBUFS; - } - - ret = dpni_load_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("dpni_load_sw_sequence failed"); - rte_free(addr); - return ret; - } - - priv->ss_iova = cfg.ss_iova; - priv->ss_offset += sp_param.size; - DPAA2_PMD_INFO("Soft parser loaded for dpni@%d", priv->hw_id); - - rte_free(addr); - return 0; -} - -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest) -{ - struct fsl_mc_io *dpni = priv->hw; - struct dpni_enable_ss_cfg cfg; - uint8_t pa[3]; - struct dpni_drv_sparser_param sp_param; - uint8_t *param_addr = NULL; - int ret; - - memset(&sp_param, 0, sizeof(sp_param)); - pa[0] = 32; /* Custom Header Length in bytes */ - sp_param.custom_header_first = 1; - sp_param.param_offset = 32; - sp_param.param_size = 1; - sp_param.start_pc = priv->ss_offset; - sp_param.param_array = (uint8_t *)&pa[0]; - - cfg.dest = dest; - cfg.ss_offset = sp_param.start_pc; - cfg.set_start = sp_param.custom_header_first; - cfg.hxs = (uint16_t)sp_param.link_to_hard_hxs; - cfg.param_offset = sp_param.param_offset; - cfg.param_size = sp_param.param_size; - if (cfg.param_size) { - param_addr = rte_malloc(NULL, cfg.param_size, 64); - if (!param_addr) { - DPAA2_PMD_ERR("Memory unavailable for soft parser param"); - return -1; - } - - memcpy(param_addr, sp_param.param_array, cfg.param_size); - cfg.param_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(param_addr, - cfg.param_size); - if (cfg.param_iova == RTE_BAD_IOVA) { - DPAA2_PMD_ERR("%s: No IOMMU map for %p, size=%d", - __func__, param_addr, cfg.param_size); - rte_free(param_addr); - - return -ENOBUFS; - } - priv->ss_param_iova = cfg.param_iova; - } else { - cfg.param_iova = 0; - } - - ret = dpni_enable_sw_sequence(dpni, CMD_PRI_LOW, priv->token, &cfg); - if (ret) { - DPAA2_PMD_ERR("Soft parser enabled for dpni@%d failed", - priv->hw_id); - rte_free(param_addr); - return ret; - } - - rte_free(param_addr); - DPAA2_PMD_INFO("Soft parser enabled for dpni@%d", priv->hw_id); - return 0; -} diff --git a/drivers/net/dpaa2/dpaa2_sparser.h b/drivers/net/dpaa2/dpaa2_sparser.h deleted file mode 100644 index 0187cde113..0000000000 --- a/drivers/net/dpaa2/dpaa2_sparser.h +++ /dev/null @@ -1,202 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018-2019 NXP - */ - -/** - * @file dpaa2_sparser.h - * - * @brief Soft parser related macros & functions support for DPAA2 device - * framework based applications. - * - */ - -#ifndef _DPAA2_SPARSER_H -#define _DPAA2_SPARSER_H - -#define WRIOP_SS_INITIALIZER(priv) \ -do { \ - /* Base offset of parse profile memory in WRIOP */ \ - (priv)->ss_offset = 0x20; \ - (priv)->ss_iova = (size_t)NULL; \ - (priv)->ss_param_iova = (size_t)NULL; \ -} while (0) - -/**************************************************************************/ -/* - * @enum parser_starting_hxs_code - * @Description PARSER Starting HXS code - */ -/***************************************************************************/ -enum parser_starting_hxs_code { - /** Ethernet Starting HXS coding */ - PARSER_ETH_STARTING_HXS = 0x0000, - /** LLC+SNAP Starting HXS coding */ - PARSER_LLC_SNAP_STARTING_HXS = 0x0001, - /** VLAN Starting HXS coding */ - PARSER_VLAN_STARTING_HXS = 0x0002, - /** PPPoE+PPP Starting HXS coding */ - PARSER_PPPOE_PPP_STARTING_HXS = 0x0003, - /** MPLS Starting HXS coding */ - PARSER_MPLS_STARTING_HXS = 0x0004, - /** ARP Starting HXS coding */ - PARSER_ARP_STARTING_HXS = 0x0005, - /** IP Starting HXS coding */ - PARSER_IP_STARTING_HXS = 0x0006, - /** IPv4 Starting HXS coding */ - PARSER_IPV4_STARTING_HXS = 0x0007, - /** IPv6 Starting HXS coding */ - PARSER_IPV6_STARTING_HXS = 0x0008, - /** GRE Starting HXS coding */ - PARSER_GRE_STARTING_HXS = 0x0009, - /** MinEncap Starting HXS coding */ - PARSER_MINENCAP_STARTING_HXS = 0x000A, - /** Other L3 Shell Starting HXS coding */ - PARSER_OTHER_L3_SHELL_STARTING_HXS = 0x000B, - /** TCP Starting HXS coding */ - PARSER_TCP_STARTING_HXS = 0x000C, - /** UDP Starting HXS coding */ - PARSER_UDP_STARTING_HXS = 0x000D, - /** IPSec Starting HXS coding */ - PARSER_IPSEC_STARTING_HXS = 0x000E, - /** SCTP Starting HXS coding */ - PARSER_SCTP_STARTING_HXS = 0x000F, - /** DCCP Starting HXS coding */ - PARSER_DCCP_STARTING_HXS = 0x0010, - /** Other L4 Shell Starting HXS coding */ - PARSER_OTHER_L4_SHELL_STARTING_HXS = 0x0011, - /** GTP Starting HXS coding */ - PARSER_GTP_STARTING_HXS = 0x0012, - /** ESP Starting HXS coding */ - PARSER_ESP_STARTING_HXS = 0x0013, - /** VXLAN Starting HXS coding */ - PARSER_VXLAN_STARTING_HXS = 0x0014, - /** L5 (and above) Shell Starting HXS coding */ - PARSER_L5_SHELL_STARTING_HXS = 0x001E, - /** Final Shell Starting HXS coding */ - PARSER_FINAL_SHELL_STARTING_HXS = 0x001F -}; - -/**************************************************************************/ -/* - * @Description struct dpni_drv_sparser_param - Structure representing the - * information needed to activate(enable) a Soft Parser. - */ -/***************************************************************************/ - -struct dpni_drv_sparser_param { - /* The "custom_header_first" must be set if the custom header to parse - * is the first header in the packet, otherwise "custom_header_first" - * must be cleared. - */ - uint8_t custom_header_first; - /* Hard HXS on which a soft parser is activated. This must be - * configured. - * if the header to parse is not the first header in the packet. - */ - enum parser_starting_hxs_code link_to_hard_hxs; - /* Soft Sequence Start PC */ - uint16_t start_pc; - /* Soft Sequence byte-code */ - uint8_t *byte_code; - /* Soft Sequence size */ - uint16_t size; - /* Pointer to the Parameters Array of the SP */ - uint8_t *param_array; - /* Parameters offset */ - uint8_t param_offset; - /* Parameters size */ - uint8_t param_size; -}; - -struct sp_parse_result { - /* Next header */ - uint16_t nxt_hdr; - /* Frame Attribute Flags Extension */ - uint16_t frame_attribute_flags_extension; - /* Frame Attribute Flags (part 1) */ - uint32_t frame_attribute_flags_1; - /* Frame Attribute Flags (part 2) */ - uint32_t frame_attribute_flags_2; - /* Frame Attribute Flags (part 3) */ - uint32_t frame_attribute_flags_3; - /* Shim Offset 1 */ - uint8_t shim_offset_1; - /* Shim Offset 2 */ - uint8_t shim_offset_2; - /* Outer IP protocol field offset */ - uint8_t ip_1_pid_offset; - /* Ethernet offset */ - uint8_t eth_offset; - /* LLC+SNAP offset */ - uint8_t llc_snap_offset; - /* First VLAN's TCI field offset*/ - uint8_t vlan_tci1_offset; - /* Last VLAN's TCI field offset*/ - uint8_t vlan_tcin_offset; - /* Last Ethertype offset*/ - uint8_t last_etype_offset; - /* PPPoE offset */ - uint8_t pppoe_offset; - /* First MPLS offset */ - uint8_t mpls_offset_1; - /* Last MPLS offset */ - uint8_t mpls_offset_n; - /* Layer 3 (Outer IP, ARP, FCoE or FIP) offset */ - uint8_t l3_offset; - /* Inner IP or MinEncap offset*/ - uint8_t ipn_or_minencap_offset; - /* GRE offset */ - uint8_t gre_offset; - /* Layer 4 offset*/ - uint8_t l4_offset; - /* Layer 5 offset */ - uint8_t l5_offset; - /* Routing header offset of 1st IPv6 header */ - uint8_t routing_hdr_offset1; - /* Routing header offset of 2nd IPv6 header */ - uint8_t routing_hdr_offset2; - /* Next header offset */ - uint8_t nxt_hdr_offset; - /* IPv6 fragmentable part offset */ - uint8_t ipv6_frag_offset; - /* Frame's untouched running sum, input to parser */ - uint16_t gross_running_sum; - /* Running Sum */ - uint16_t running_sum; - /* Parse Error code */ - uint8_t parse_error_code; - /* Offset to the next header field before IPv6 fragment extension */ - uint8_t nxt_hdr_before_ipv6_frag_ext; - /* Inner IP Protocol field offset */ - uint8_t ip_n_pid_offset; - /* Reserved for Soft parsing context*/ - uint8_t soft_parsing_context[21]; -}; - -struct frame_attr { - const char *fld_name; - uint8_t faf_offset; - uint32_t fld_mask; -}; - -struct frame_attr_ext { - const char *fld_name; - uint8_t faf_ext_offset; - uint16_t fld_mask; -}; - - -struct parse_err { - uint16_t code; - const char *err_name; -}; - -/* Macro definitions */ -#define IS_ONE_BIT_FIELD(_mask) \ -(!((_mask) & ((_mask) - 1)) || (_mask == 1)) - -int dpaa2_eth_load_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -int dpaa2_eth_enable_wriop_soft_parser(struct dpaa2_dev_priv *priv, - enum dpni_soft_sequence_dest dest); -#endif /* _DPAA2_SPARSER_H_ */ diff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build index 4094ea02ba..b821f7bfad 100644 --- a/drivers/net/dpaa2/meson.build +++ b/drivers/net/dpaa2/meson.build @@ -16,7 +16,6 @@ sources = files( 'dpaa2_flow.c', 'dpaa2_recycle.c', 'dpaa2_rxtx.c', - 'dpaa2_sparser.c', 'dpaa2_ptp.c', 'mc/dprtc.c', 'mc/dpkg.c', -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v12-S2 10/11] net/dpaa2: remove unused soft parser driver 2026-10-16 7:03 ` [PATCH v12-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-20 13:45 ` Stephen Hemminger 0 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-20 13:45 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev, Jun Yang On Fri, 16 Oct 2026 12:33:38 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > From: Jun Yang <jun.yang@nxp.com> > > The DPAA2 soft parser (SP) byte code has to be installed by the boot > firmware before Linux starts; the WRIOP parser cannot be reprogrammed once > the MC is up. Loading an SP image at run time from the PMD therefore never > took effect, so the loader and its DPNI_SS_INGRESS plumbing were dead > code and are removed. > > The rte_flow VXLAN and eCPRI pattern items were only ever accepted while > an SP image was believed to be loaded. With the SP gone they are rejected > by dpaa2_dev_verify_patterns() before the configure switch is reached, so > their handlers dpaa2_configure_flow_vxlan() and > dpaa2_configure_flow_ecpri(), the switch cases that call them, the mask > descriptors and the VXLAN_HF_VNI helper are removed as well. The eCPRI item > is also removed from the dpaa2 feature matrix so that the documented > capabilities match the code. > > Signed-off-by: Jun Yang <jun.yang@nxp.com> > Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> > --- Sigh. AI review said "I am sorry last review was wrong.." Subject: Re: [PATCH v13-S2 00/10] net/dpaa2: ... Series applies cleanly to 26.11-rc1 and every commit builds with -Dwerror=true. Feature matrix now matches the code. v12 comments on patches 1, 7, 9 and 10 are addressed. One problem left, in patch 6. Still needs a separate fix, outside this series: dpaa2_flow_item_convert() allocates num items and writes num + 1 (the END marker). Patch 06/10 net/dpaa2: set default flow miss action per device Error: My v12 comment got the mechanism wrong. priv->nb_rx_queues is the DPNI hardware count (num_rx_tcs * num_queues), not the application's queue count, so dist_size - 1 is always a valid FS flow id. The problem is that the queue may not be set up. Rx queue i maps to tc = i / dist_size, flow = i % dist_size, and dpni_set_queue() and the taildrop setup only run in dpaa2_dev_rx_queue_setup(). On a 16-queue DPNI where the application configures 4 Rx queues, unmatched frames go to flow 15. Nothing polls that FQ and it has no taildrop, so frames pile up and hold buffers until the pool runs out and Rx stops on every queue. The old default of 0 was always polled. Use the last queue the application actually configured in this TC: uint16_t nb_rxq = priv->eth_dev->data->nb_rx_queues; uint16_t first = tc_id * dist_size; tc_cfg.enable = true; tc_cfg.fs_miss_flow_id = nb_rxq > first ? RTE_MIN(dist_size, nb_rxq - first) - 1 : 0; Warning: Release note says the miss flow id "defaults to the lowest-priority flow of the device". An FS flow id is a queue index within the TC, not a priority. Say which queue gets unmatched frames, e.g.: The flow steering miss queue now defaults to the last Rx queue configured in the traffic class. Patch 09/10 net/dpaa2: parse tunnel and fragmented packet types Info: DPAA2_PKT_TYPE_IPV4_ICMP is now (0x0003 | DPAA2_PKT_TYPE_IPV4_FRAG), which reads as if ICMP were a fragment. The value is the same either way; write it as (0x0003 | DPAA2_PKT_TYPE_IPV4), and the same for IPv6. Patch 01/10 net/dpaa2: fix integer overflow in CCSR region mapping Info: PAGE_SIZE and PAGE_MASK in dpaa2_recycle.c are now unused. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v12-S2 11/11] net/dpaa2: rename Rx queue flags 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (9 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta @ 2026-10-16 7:03 ` Prashant Gupta 2026-10-16 16:18 ` [PATCH v12-S2 00/11] net/dpaa2 updates Stephen Hemminger 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta 12 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-16 7:03 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 6 ++++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 4f5e738965..b3a1631923 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -550,7 +550,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1041,7 +1041,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1521,7 +1521,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3475,7 +3475,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3581,7 +3581,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index c68e24cbb8..5e3f8f2f78 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -98,9 +98,11 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) + +#define DPAA2_RX_PRINT_PSR_RESULT_FLAG RTE_BIT32(12) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 052133eb55..e83fa8c158 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -831,7 +831,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (!by_channel) { struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); } @@ -1096,7 +1096,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v12-S2 00/11] net/dpaa2 updates 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (10 preceding siblings ...) 2026-10-16 7:03 ` [PATCH v12-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-16 16:18 ` Stephen Hemminger 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta 12 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-16 16:18 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Fri, 16 Oct 2026 12:33:28 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > Changes in v12: > - Restore VXLAN rte_flow item documentation in dpaa2.ini to > keep documentation aligned with PMD capabilities. > - Fix documentation check failure reported after application > to next-net. This is worse not better. Subject: Re: [PATCH v12-S2 00/11] net/dpaa2: ... Series applies cleanly to 26.11-rc1 and every commit builds with -Dwerror=true. The doc-vs-code problem is not fixed, it is now hidden. Patch 10 removes VXLAN support but leaves "vxlan = Y" in the feature matrix. check-doc-vs-code.sh passes only because a stray RTE_FLOW_ITEM_TYPE_VXLAN reference survives in dpaa2_flow_item_convert(). Pre-existing, separate fix needed: dpaa2_flow_item_convert() allocates one item too few. For "eth / end" num ends at 1, rte_malloc() gets 1 * sizeof(item), then new_pattern[1] is written for the END marker. An empty pattern also reads pattern[1] past the end. for (num = 0; pattern[num].type != RTE_FLOW_ITEM_TYPE_END; num++) ; new_pattern = rte_malloc(NULL, sizeof(*new_pattern) * (num + 1), RTE_CACHE_LINE_SIZE); Patch 06/11 net/dpaa2: set default flow miss action per device Error: default_flow = min(fs_entries, dist_queues) - 1 is computed at probe from hardware attributes, but fs_miss_flow_id is a queue index inside the TC distribution, and dist_size is nb_rx_queues / num_rx_tc set at configure time. A DPNI with 16 queues where the app configures 4 Rx queues gets fs_miss_flow_id 15 with dist_size 4: either MC rejects dpni_set_rx_fs_dist() and every rte_flow create fails, or unmatched frames go to an unconfigured queue. The old default (0) was always valid. fs_entries is the FS table size, not a flow id, and should not be in this expression at all. Compute it where dist_size is known and drop the priv field: tc_cfg.enable = true; tc_cfg.fs_miss_flow_id = dist_size - 1; Or keep 0. Either way the release note must say which queue gets unmatched frames. Patch 07/11 net/dpaa2: identify Rx mbuf hash information by FLC Warning: Commit message says TC and flow id are stored via rte_mbuf_sched_set(); the code writes m->hash.fdir.hi. Fix the message. RTE_MBUF_F_RX_FDIR_ID means hash.fdir.hi holds the id from a MARK action. This driver has no MARK action, so applications see a synthetic (tc << 16) | flow value as if it were a mark. Set only RTE_MBUF_F_RX_FDIR, or implement RTE_FLOW_ACTION_TYPE_MARK. Patch 09/11 net/dpaa2: parse tunnel and fragmented packet types Warning: Parse summary 0x0001 was mapped to RTE_PTYPE_L3_IPV4_EXT (options present). Now it is L3_IPV4_EXT | L4_FRAG. The slow path treats options (L3_IP_1_OPT_PRESENT) and fragments (L3_IP_1_*_FRAGMENT) as independent bits, so one summary code cannot mean both. If 0x0001 is the fragment code, the mapping should be: case DPAA2_PKT_TYPE_IPV4_EXT: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; and the IPV4_EXT/IPV6_EXT names should be changed to match. If it is the options code, drop L4_FRAG. Patch 10/11 net/dpaa2: remove unused soft parser driver Error: doc/guides/nics/features/dpaa2.ini still has "vxlan = Y". Commit message and release note both say the item is no longer advertised. -vxlan = Y The leftover VXLAN check in dpaa2_flow_item_convert() is what keeps the doc-vs-code script quiet. Remove it: - if (pattern[num].type == RTE_FLOW_ITEM_TYPE_VXLAN) - tunnel_start = 1; - else if (tunnel_start) - new_pattern[num].in_tunnel = 1; Error: dpaa2_flow_create() does not call dpaa2_flow_validate(), and the default case in dpaa2_generic_flow_set() sets ret = -ENOTSUP and breaks out of the switch without leaving the loop; the action loop then overwrites ret. With the VXLAN/ECPRI cases removed, "eth / ipv4 / udp / vxlan / end actions queue index 1" now creates a rule matching all UDP. Fix before (or in) this patch: default: DPAA2_PMD_ERR("Invalid flow item[%d] type(%d)", i, pattern[i].type); ret = -ENOTSUP; - break; + goto end_flow_set; Warning: Removing the VXLAN/ECPRI cases in dpaa2_flow_extract_support() left two dead "break;" lines after the GRE case. Leftovers from the removal: dpaa2_ethdev.h: dpaa2_soft_parser_loaded() prototype dpaa2_ethdev.h: ss_offset, ss_iova, ss_param_iova in dpaa2_dev_priv dpaa2_ethdev.h: DPAA2_ECPRI_MAX_EXTRACT_NB dpaa2_flow.c: #include <sys/mman.h> Info: With VXLAN gone nothing sets in_tunnel, so tunnel_start and every "if (dpaa2_pattern->in_tunnel)" branch in the configure handlers is dead. Fine as a follow-up. Patch 11/11 net/dpaa2: rename Rx queue flags Warning: Commit message says mechanical rename, but it adds DPAA2_RX_PRINT_PSR_RESULT_FLAG, which nothing uses. Drop it. Patch 01/11 net/dpaa2: fix integer overflow in CCSR region mapping Warning: Second paragraph of the commit message is wrong. For len 4096 on a 64K-page kernel the old code masked len to 0 and then bumped it to PAGE_SIZE, so the mapping did not fail. The real defect is that the old length ignored offset, so a region crossing a page boundary was not fully mapped. Since this goes to stable, the message should say that. Info: PAGE_SIZE and PAGE_MASK in dpaa2_recycle.c are now unused; remove. Patch 03/11 net/dpaa2: support larger burst size Info: Limit for non-LX2160A (and LX2160A with dpni < 8.7) drops from 65536 to 0xF7FF. Mention that in the commit message. Write 0x37FFF instead of 229375 so it matches the fsl_dpni.h comment. ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v13-S2 00/10] net/dpaa2 updates 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta ` (11 preceding siblings ...) 2026-10-16 16:18 ` [PATCH v12-S2 00/11] net/dpaa2 updates Stephen Hemminger @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (10 more replies) 12 siblings, 11 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev Changes in v13: - Fix CCSR region mapping commit message to describe the actual page-boundary mapping issue. - Use the configured Rx distribution table size when selecting the default flow miss action. - Remove incorrect RTE_MBUF_F_RX_FDIR_ID usage and update the associated commit message. - Rename IPv4/IPv6 fragment parser summary definitions and report fragmented packets using RTE_PTYPE_L4_FRAG. - Remove unused DPAA2_RX_PRINT_PSR_RESULT_FLAG. - Drop "net/dpaa2: remove unused soft parser driver". Series overview: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, - support the flow drop action and a default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - parse tunnel and fragmented packet types, - rename Rx queue flags. Gagandeep Singh (6): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (3): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: parse tunnel and fragmented packet types Jun Yang (1): net/dpaa2: rename Rx queue flags doc/guides/nics/features/dpaa2.ini | 2 + doc/guides/rel_notes/release_26_11.rst | 4 + drivers/net/dpaa2/dpaa2_ethdev.c | 54 +++-- drivers/net/dpaa2/dpaa2_ethdev.h | 32 ++- drivers/net/dpaa2/dpaa2_flow.c | 281 +++++++++++++++++++++++-- drivers/net/dpaa2/dpaa2_recycle.c | 23 +- drivers/net/dpaa2/dpaa2_rxtx.c | 66 ++++-- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 8 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- 11 files changed, 413 insertions(+), 87 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v13-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 02/10] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (9 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region(), PAGE_SIZE is defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and mmap() length calculations, leading to an integer overflow (Coverity CID 49765682). The old code also computed the mapping length without taking the address offset within the page into account. As a result, regions crossing a page boundary might not be fully mapped. The mapping size must cover the entire range from the page-aligned start address through offset + len. Fix by validating the page size returned by sysconf(), deriving the page mask from the validated value, and using RTE_ALIGN_CEIL(offset + len, page_size) to calculate the mapping length. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 02/10] net/dpaa2: set Tx confirmation on device init 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 03/10] net/dpaa2: support larger burst size Prashant Gupta ` (8 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 03/10] net/dpaa2: support larger burst size 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 02/10] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (7 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (2 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 03/10] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 05/10] net/dpaa2: support flow drop action Prashant Gupta ` (6 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 05/10] net/dpaa2: support flow drop action 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (3 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 06/10] net/dpaa2: set default flow miss action per device Prashant Gupta ` (5 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 06/10] net/dpaa2: set default flow miss action per device 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (4 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 05/10] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (4 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Remove the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable and use the last entry in the configured Rx distribution table as the default flow steering miss action. Users who relied on the environment variable must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 4 ++++ drivers/net/dpaa2/dpaa2_flow.c | 14 +------------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..1b22d134ae 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -105,6 +105,10 @@ New Features * Added the inner IP header to the RSS hash so tunneled traffic is distributed across the Rx queues. + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + per-device FS table miss flow id now defaults to the lowest-priority + flow of the device. Users who previously redirected unmatched frames + to a specific queue via this variable must use the rte_flow API instead. * **Updated NXP ENETC4 PMD.** diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..48f2861f83 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4590,7 +4589,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, return 0; tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = dist_size - 1; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5223,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (5 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 06/10] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 08/10] net/dpaa2: add minimum key size support Prashant Gupta ` (3 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure flow steering actions with FLC enabled to align the stashing settings with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in the FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are encoded in hash.fdir.hi. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..2569b2bd83 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 48f2861f83..4f7716ab66 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..71e292fea6 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + m->hash.fdir.hi = (tc << 16) | flow; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 08/10] net/dpaa2: add minimum key size support 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (6 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (2 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Support for 24-byte QoS key entries is available from DPNI version 8.7 onwards. For older DPNI versions, the existing 56-byte entry size is retained to maintain compatibility. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 4f7716ab66..c670ee9cca 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4519,7 +4522,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4529,11 +4532,11 @@ dpaa2_flow_entry_size(uint16_t key_max_size) return 0; } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || + dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int @@ -4595,7 +4598,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4686,7 +4689,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4977,11 +4980,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (7 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 08/10] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 10/10] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to identify IPv4/IPv6 fragmented packets, IPsec ESP, and GTP-U/GTP-C packets. Map the corresponding parser summary values to DPDK packet types. Fragmented IPv4/IPv6 packets are reported with RTE_PTYPE_L4_FRAG. GTP-U and GTP-C packets are additionally marked with RTE_PTYPE_L4_UDP to reflect the UDP transport used by the outer tunnel header. Advertise the newly supported packet types through dpaa2_supported_ptypes_get(). Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 +++ drivers/net/dpaa2/dpaa2_ethdev.h | 20 ++++++++++++--- drivers/net/dpaa2/dpaa2_rxtx.c | 44 ++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..72b37a988d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 2569b2bd83..dc72939103 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -127,9 +127,9 @@ #define DPAA2_PKT_TYPE_ETHER 0x0060 #define DPAA2_PKT_TYPE_IPV4 0x0000 #define DPAA2_PKT_TYPE_IPV6 0x0020 -#define DPAA2_PKT_TYPE_IPV4_EXT \ +#define DPAA2_PKT_TYPE_IPV4_FRAG \ (0x0001 | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_EXT \ +#define DPAA2_PKT_TYPE_IPV6_FRAG \ (0x0001 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (0x000e | DPAA2_PKT_TYPE_IPV4) @@ -144,9 +144,21 @@ #define DPAA2_PKT_TYPE_IPV6_SCTP \ (0x000f | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (0x0003 | DPAA2_PKT_TYPE_IPV4_FRAG) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) + (0x0003 | DPAA2_PKT_TYPE_IPV6_FRAG) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0160 #define DPAA2_PKT_TYPE_VLAN_2 0x0260 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 71e292fea6..c2c581f69b 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -76,14 +76,6 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; - break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; @@ -116,6 +108,42 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v13-S2 10/10] net/dpaa2: rename Rx queue flags 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (8 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-19 18:34 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-19 18:34 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 4 ++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 72b37a988d..6afd641709 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -551,7 +551,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1042,7 +1042,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1522,7 +1522,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3476,7 +3476,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3580,7 +3580,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index b48c0d7cf2..12af00cc3c 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -98,9 +98,9 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c2c581f69b..df3eefc134 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -829,7 +829,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (!by_channel) { struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); } @@ -1094,7 +1094,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 00/10] net/dpaa2 updates 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta ` (9 preceding siblings ...) 2026-10-19 18:34 ` [PATCH v13-S2 10/10] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta ` (10 more replies) 10 siblings, 11 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev Changes in v14: - Use the last Rx queue configured in each traffic class as the default flow steering miss queue. - Update the release note accordingly. Series overview: - fix an integer overflow in the CCSR region mapping, - set Tx confirmation on device init and support a larger burst size, - support MPLS and PPPoE flow distribution, - support the flow drop action and a default flow miss action, - identify Rx mbuf hash information by FLC and add minimum key size support, - parse tunnel and fragmented packet types, - rename Rx queue flags. Gagandeep Singh (6): net/dpaa2: set Tx confirmation on device init net/dpaa2: support larger burst size net/dpaa2: support MPLS and PPPoE flow distribution net/dpaa2: support flow drop action net/dpaa2: set default flow miss action per device net/dpaa2: identify Rx mbuf hash information by FLC Hemant Agrawal (3): net/dpaa2: fix integer overflow in CCSR region mapping net/dpaa2: add minimum key size support net/dpaa2: parse tunnel and fragmented packet types Jun Yang (1): net/dpaa2: rename Rx queue flags doc/guides/nics/features/dpaa2.ini | 2 + doc/guides/rel_notes/release_26_11.rst | 5 + drivers/net/dpaa2/dpaa2_ethdev.c | 54 +++-- drivers/net/dpaa2/dpaa2_ethdev.h | 36 +++- drivers/net/dpaa2/dpaa2_flow.c | 285 +++++++++++++++++++++++-- drivers/net/dpaa2/dpaa2_recycle.c | 23 +- drivers/net/dpaa2/dpaa2_rxtx.c | 66 ++++-- drivers/net/dpaa2/dpaa2_tm.c | 16 +- drivers/net/dpaa2/mc/dpni.c | 11 +- drivers/net/dpaa2/mc/fsl_dpni.h | 8 +- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 +- 11 files changed, 420 insertions(+), 89 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 356+ messages in thread
* [PATCH v14-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 02/10] net/dpaa2: set Tx confirmation on device init Prashant Gupta ` (9 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: stable, Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> In lsx_ccsr_map_region(), PAGE_SIZE is defined as sysconf(_SC_PAGESIZE), which returns a signed long and may be negative on error. The value was used directly in size_t comparisons and mmap() length calculations, leading to an integer overflow (Coverity CID 49765682). The old code also computed the mapping length without taking the address offset within the page into account. As a result, regions crossing a page boundary might not be fully mapped. The mapping size must cover the entire range from the page-aligned start address through offset + len. Fix by validating the page size returned by sysconf(), deriving the page mask from the validated value, and using RTE_ALIGN_CEIL(offset + len, page_size) to calculate the mapping length. Coverity issue: 49765682 Fixes: f023d059769f ("net/dpaa2: support recycle loopback port") Cc: stable@dpdk.org Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_recycle.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c index f78d12362e..9b6ae3f515 100644 --- a/drivers/net/dpaa2/dpaa2_recycle.c +++ b/drivers/net/dpaa2/dpaa2_recycle.c @@ -176,6 +176,9 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) void *tmp; uint64_t start; uint64_t offset; + uint64_t page_mask; + long page_size; + size_t map_len; fd = open("/dev/mem", O_RDWR); if (fd < 0) { @@ -183,20 +186,24 @@ static void *lsx_ccsr_map_region(uint64_t addr, size_t len) return NULL; } - start = addr & PAGE_MASK; + page_size = sysconf(_SC_PAGESIZE); + if (page_size <= 0) { + close(fd); + return NULL; + } + page_mask = ~((uint64_t)page_size - 1); + start = addr & page_mask; offset = addr - start; - len = len & PAGE_MASK; - if (len < (size_t)PAGE_SIZE) - len = PAGE_SIZE; + map_len = RTE_ALIGN_CEIL(offset + len, (size_t)page_size); - tmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); + tmp = mmap(NULL, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); close(fd); - if (tmp != MAP_FAILED) - return (uint8_t *)tmp + offset; - else + if (tmp == MAP_FAILED) return NULL; + + return (uint8_t *)tmp + offset; } static const uint8_t ls_sd1_prot_idx_map[] = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 02/10] net/dpaa2: set Tx confirmation on device init 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 03/10] net/dpaa2: support larger burst size Prashant Gupta ` (8 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang, Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Move TX confirmation mode setting from TXQ setup to device initialization because TXQ0 is not always set up by the user. Signed-off-by: Jun Yang <jun.yang@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 40 ++++++++++++-------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 8ae4fd89c5..f88ecb88aa 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1153,7 +1153,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, struct dpni_queue tx_conf_cfg; struct dpni_queue tx_flow_cfg; uint8_t options = 0, flow_id; - uint8_t ceetm_ch_idx; uint16_t channel_id; struct dpni_queue_id qid; uint32_t tc_id; @@ -1174,30 +1173,6 @@ dpaa2_dev_tx_queue_setup(struct rte_eth_dev *dev, memset(&tx_conf_cfg, 0, sizeof(struct dpni_queue)); memset(&tx_flow_cfg, 0, sizeof(struct dpni_queue)); - if (!tx_queue_id) { - for (ceetm_ch_idx = 0; - ceetm_ch_idx <= (priv->num_channels - 1); - ceetm_ch_idx++) { - /*Set tx-conf and error configuration*/ - if (priv->flags & DPAA2_TX_CONF_ENABLE) { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_AFFINE); - } else { - ret = dpni_set_tx_confirmation_mode(dpni, - CMD_PRI_LOW, priv->token, - ceetm_ch_idx, - DPNI_CONF_DISABLE); - } - if (ret) { - DPAA2_PMD_ERR("Error(%d) in tx conf setting", - ret); - return ret; - } - } - } - tc_id = tx_queue_id % priv->num_tx_tc; channel_id = (uint8_t)(tx_queue_id / priv->num_tx_tc) % priv->num_channels; flow_id = 0; @@ -3621,6 +3596,21 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) goto init_err; } + for (i = 0; i < priv->num_channels; i++) { + /*Set tx-conf and error configuration*/ + if (priv->flags & DPAA2_TX_CONF_ENABLE) { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_AFFINE); + } else { + ret = dpni_set_tx_confirmation_mode(dpni_dev, + CMD_PRI_LOW, priv->token, i, DPNI_CONF_DISABLE); + } + if (ret) { + DPAA2_PMD_ERR("Error(%d) in tx conf setting", ret); + goto init_err; + } + } + /* Allocate memory for storing MAC addresses. * Table of mac_filter_entries size is allocated so that RTE ether lib * can add MAC entries when rte_eth_dev_mac_addr_add is called. -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 03/10] net/dpaa2: support larger burst size 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 02/10] net/dpaa2: set Tx confirmation on device init Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta ` (7 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Make burst size checks and MC command fields SoC-aware, enabling bursts larger than 64K on LX2160A with dpni version 8.7+. The max_burst_size field in dpni_tx_shaping_cfg is widened to uint32_t and the MC command struct is updated to split the value across two 16-bit fields using the new DPNI_BURST_LO/HI macros. Signed-off-by: Prashant Gupta <prashant.gupta_3@nxp.com> Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_tm.c | 16 +++++++++++----- drivers/net/dpaa2/mc/dpni.c | 11 +++++++++-- drivers/net/dpaa2/mc/fsl_dpni.h | 8 ++++++-- drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 3 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_tm.c b/drivers/net/dpaa2/dpaa2_tm.c index 36e815c356..3057f4d031 100644 --- a/drivers/net/dpaa2/dpaa2_tm.c +++ b/drivers/net/dpaa2/dpaa2_tm.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2020-2024 NXP + * Copyright 2020-2026 NXP */ #include <rte_ethdev.h> @@ -10,14 +10,20 @@ #include "dpaa2_pmd_logs.h" #include <dpaa2_hw_dpio.h> -#define DPAA2_BURST_MAX (64 * 1024) - #define DPAA2_SHAPER_MIN_RATE 0 #define DPAA2_SHAPER_MAX_RATE 107374182400ull #define DPAA2_WEIGHT_MAX 24701 #define DPAA2_PKT_ADJUST_LEN_MIN 0 #define DPAA2_PKT_ADJUST_LEN_MAX 0x7ff +static inline uint32_t dpaa2_get_burst_max(struct dpaa2_dev_priv *priv) +{ + if (dpaa2_dev_cmp_dpni_ver(priv, 8, 7) >= 0) + return (dpaa2_svr_family == SVR_LX2160A) ? 229375 : 0xF7FF; + + return 0xF7FF; +} + int dpaa2_tm_init(struct rte_eth_dev *dev) { @@ -283,7 +289,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "committed rate is out of range\n"); - if (params->committed.size > DPAA2_BURST_MAX) + if (params->committed.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "committed size is out of range\n"); @@ -293,7 +299,7 @@ dpaa2_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE, NULL, "Peak rate is out of range\n"); - if (params->peak.size > DPAA2_BURST_MAX) + if (params->peak.size > dpaa2_get_burst_max(priv)) return -rte_tm_error_set(error, EINVAL, RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE, NULL, "Peak size is out of range\n"); diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c index d0a9fefd31..17275b7195 100644 --- a/drivers/net/dpaa2/mc/dpni.c +++ b/drivers/net/dpaa2/mc/dpni.c @@ -1106,6 +1106,7 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, { struct dpni_cmd_set_tx_shaping *cmd_params; struct mc_command cmd = { 0 }; + uint32_t tx_cr_burst, tx_er_burst; int coupled, lni_shaper; uint8_t channel_id; uint16_t oal; @@ -1115,10 +1116,16 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, cmd_flags, token); cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params; + tx_cr_burst = tx_cr_shaper->max_burst_size; + tx_er_burst = tx_er_shaper->max_burst_size; cmd_params->tx_cr_max_burst_size = - cpu_to_le16(tx_cr_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_cr_burst)); cmd_params->tx_er_max_burst_size = - cpu_to_le16(tx_er_shaper->max_burst_size); + cpu_to_le16(DPNI_BURST_LO(tx_er_burst)); + cmd_params->tx_cr_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_cr_burst)); + cmd_params->tx_er_max_burst_size_hi = + cpu_to_le16(DPNI_BURST_HI(tx_er_burst)); cmd_params->tx_cr_rate_limit = cpu_to_le32(tx_cr_shaper->rate_limit); cmd_params->tx_er_rate_limit = diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h index 42d633eaf8..8913b408e7 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni.h +++ b/drivers/net/dpaa2/mc/fsl_dpni.h @@ -830,14 +830,18 @@ int dpni_get_link_state(struct fsl_mc_io *mc_io, uint16_t token, struct dpni_link_state *state); +#define DPNI_BURST_LO(burst) ((burst) & GENMASK(15, 0)) +#define DPNI_BURST_HI(burst) ((burst) >> 16) + /** * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration * @rate_limit: Rate in Mbits/s - * @max_burst_size: Burst size in bytes (up to 64KB) + * @max_burst_size: Burst size in bytes. Limits depend on the SoC (0x37FFF + * for LX2160A, 0xF7FF for all others) */ struct dpni_tx_shaping_cfg { uint32_t rate_limit; - uint16_t max_burst_size; + uint32_t max_burst_size; }; /** diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h index bb4939031b..6b396ca7cc 100644 --- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h @@ -394,7 +394,8 @@ struct dpni_rsp_get_link_state { struct dpni_cmd_set_tx_shaping { uint16_t tx_cr_max_burst_size; uint16_t tx_er_max_burst_size; - uint32_t pad; + uint16_t tx_cr_max_burst_size_hi; + uint16_t tx_er_max_burst_size_hi; uint32_t tx_cr_rate_limit; uint32_t tx_er_rate_limit; /* from LSB: coupled:1, lni_shaper: 1*/ -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (2 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 03/10] net/dpaa2: support larger burst size Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 05/10] net/dpaa2: support flow drop action Prashant Gupta ` (6 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add rte_flow pattern support for MPLS and PPPoE items in the dpaa2 PMD flow engine. For a pattern with no spec/mask, the frame is identified by its Frame Attribute Flag (FAF_MPLS_FRAM / FAF_PPPOE_PPP_FRAM) for both the QoS and flow steering tables. When a spec is present, the MPLS label (NH_FLD_MPLS_MPLSL_1) or the PPPoE session id (NH_FLD_PPPOE_SID) is added as a header extract rule for both tables. NH_FLD_MPLS_MPLSL_1 with DPKG_FULL_FIELD causes MC to extract the full 4-byte MPLS LSE (label + TC + S + TTL). The original code passed sizeof(label_tc_s) = 3, so the driver key profile recorded the field as 3 bytes while MC placed 4 bytes in the key; any extract field added after MPLS was off by one byte, corrupting the key layout. Fix by passing the full struct rte_flow_item_mpls pointer (spec/mask) with sizeof(*mask) = 4, so the key profile width matches the 4-byte field that MC extracts. The TTL byte has mask 0x00 in the default mask and is ignored for matching purposes. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/nics/features/dpaa2.ini | 2 + drivers/net/dpaa2/dpaa2_flow.c | 196 +++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/doc/guides/nics/features/dpaa2.ini b/doc/guides/nics/features/dpaa2.ini index 4788afef8d..49faebcd06 100644 --- a/doc/guides/nics/features/dpaa2.ini +++ b/doc/guides/nics/features/dpaa2.ini @@ -43,6 +43,8 @@ gtp = Y icmp = Y ipv4 = Y ipv6 = Y +mpls = Y +pppoes = Y raw = Y sctp = Y tcp = Y diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 2e44bff766..1446b14bf2 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -80,6 +80,8 @@ enum rte_flow_item_type dpaa2_hp_supported_pattern_type[] = { RTE_FLOW_ITEM_TYPE_GTP, RTE_FLOW_ITEM_TYPE_ESP, RTE_FLOW_ITEM_TYPE_AH, + RTE_FLOW_ITEM_TYPE_MPLS, + RTE_FLOW_ITEM_TYPE_PPPOES, RTE_FLOW_ITEM_TYPE_RAW }; @@ -180,8 +182,17 @@ static const struct rte_flow_item_gtp dpaa2_flow_item_gtp_mask = { .teid = RTE_BE32(0xffffffff), }; +static const struct rte_flow_item_mpls dpaa2_flow_item_mpls_mask = { + .label_tc_s = { 0xff, 0xff, 0xff }, +}; + +static const struct rte_flow_item_pppoe dpaa2_flow_item_pppoe_mask = { + .session_id = RTE_BE16(0xffff), +}; + #endif + #define DPAA2_FLOW_DUMP printf static inline void @@ -1764,6 +1775,14 @@ dpaa2_flow_extract_support(const uint8_t *mask_src, mask_support = (const char *)&dpaa2_flow_item_gtp_mask; size = sizeof(struct rte_flow_item_gtp); break; + case RTE_FLOW_ITEM_TYPE_MPLS: + mask_support = (const char *)&dpaa2_flow_item_mpls_mask; + size = sizeof(struct rte_flow_item_mpls); + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + mask_support = (const char *)&dpaa2_flow_item_pppoe_mask; + size = sizeof(struct rte_flow_item_pppoe); + break; default: return -EINVAL; } @@ -4041,6 +4060,163 @@ dpaa2_configure_flow_gtp(struct dpaa2_dev_flow *flow, return 0; } +static int +dpaa2_configure_flow_mpls(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_mpls *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_mpls_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-MPLS distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_MPLS_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_MPLS); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of MPLS not support."); + return ret; + } + + if (!mask->label_tc_s[0] && !mask->label_tc_s[1] && + !mask->label_tc_s[2]) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_MPLS, + NH_FLD_MPLS_MPLSL_1, spec, + mask, sizeof(*mask), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + +static int +dpaa2_configure_flow_pppoe(struct dpaa2_dev_flow *flow, + struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_dpaa2_flow_item *dpaa2_pattern, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error __rte_unused, + int *device_configured) +{ + int ret, local_cfg = 0; + uint32_t group; + const struct rte_flow_item_pppoe *spec, *mask; + struct dpaa2_dev_priv *priv = dev->data->dev_private; + const struct rte_flow_item *pattern = + &dpaa2_pattern->generic_item; + + group = attr->group; + + /* Parse pattern list to get the matching parameters */ + spec = pattern->spec; + mask = pattern->mask ? + pattern->mask : &dpaa2_flow_item_pppoe_mask; + + /* Get traffic class index and flow id to be configured */ + flow->tc_id = group; + flow->tc_index = attr->priority; + + if (dpaa2_pattern->in_tunnel) { + DPAA2_PMD_ERR("Tunnel-PPPoE distribution not support"); + return -ENOTSUP; + } + + if (!spec) { + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_QOS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + ret = dpaa2_flow_identify_by_faf(priv, flow, + FAF_PPPOE_PPP_FRAM, DPAA2_FLOW_FS_TYPE, + group, &local_cfg); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + return 0; + } + + ret = dpaa2_flow_extract_support((const uint8_t *)mask, + RTE_FLOW_ITEM_TYPE_PPPOES); + if (ret) { + DPAA2_PMD_WARN("Extract field(s) of PPPoE not support."); + return ret; + } + + if (!mask->session_id) + return 0; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_QOS_TYPE); + if (ret) + return ret; + + ret = dpaa2_flow_add_hdr_extract_rule(flow, NET_PROT_PPPOE, + NH_FLD_PPPOE_SID, &spec->session_id, + &mask->session_id, sizeof(rte_be16_t), + priv, group, &local_cfg, DPAA2_FLOW_FS_TYPE); + if (ret) + return ret; + + (*device_configured) |= local_cfg; + + return 0; +} + static int dpaa2_configure_flow_raw(struct dpaa2_dev_flow *flow, struct rte_eth_dev *dev, @@ -4712,6 +4888,26 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, goto end_flow_set; } break; + case RTE_FLOW_ITEM_TYPE_MPLS: + ret = dpaa2_configure_flow_mpls(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("MPLS flow config failed!"); + goto end_flow_set; + } + break; + case RTE_FLOW_ITEM_TYPE_PPPOES: + ret = dpaa2_configure_flow_pppoe(flow, + dev, attr, &dpaa2_pattern[i], + actions, error, + &is_keycfg_configured); + if (ret) { + DPAA2_PMD_ERR("PPPoE flow config failed!"); + goto end_flow_set; + } + break; case RTE_FLOW_ITEM_TYPE_RAW: ret = dpaa2_configure_flow_raw(flow, dev, attr, &dpaa2_pattern[i], -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 05/10] net/dpaa2: support flow drop action 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (3 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 06/10] net/dpaa2: set default flow miss action per device Prashant Gupta ` (5 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Add support for the RTE_FLOW_ACTION_TYPE_DROP action in the dpaa2 flow engine. A flow rule with a drop action is programmed into the flow steering (FS) table with the DPNI_FS_OPT_DISCARD option so that matching frames are discarded by hardware. The drop action is added to the supported action list, accepted during action verification, configured in the FS action path, handled in the generic flow-set action loop, and cleaned up in the flow destroy path. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 1446b14bf2..f0748081b3 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -97,7 +97,8 @@ enum rte_flow_action_type dpaa2_supported_action_type[] = { RTE_FLOW_ACTION_TYPE_QUEUE, RTE_FLOW_ACTION_TYPE_PORT_ID, RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT, - RTE_FLOW_ACTION_TYPE_RSS + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_DROP }; #ifndef __cplusplus @@ -4421,6 +4422,7 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, break; case RTE_FLOW_ACTION_TYPE_PF: /* Skip this action, have to add for vxlan */ + case RTE_FLOW_ACTION_TYPE_DROP: break; case RTE_FLOW_ACTION_TYPE_END: end_of_list = 1; @@ -4468,6 +4470,8 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, flow->fs_action_cfg.redirect_obj_token = dest_priv->token; flow->fs_action_cfg.flow_id = dest_q->flow_id; + } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_DROP) { + flow->fs_action_cfg.options = DPNI_FS_OPT_DISCARD; } return 0; @@ -4945,6 +4949,7 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: ret = dpaa2_configure_flow_fs_action(priv, flow, &actions[j]); if (ret) @@ -5346,6 +5351,7 @@ dpaa2_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *_flow, case RTE_FLOW_ACTION_TYPE_QUEUE: case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: case RTE_FLOW_ACTION_TYPE_PORT_ID: + case RTE_FLOW_ACTION_TYPE_DROP: if (priv->num_rx_tc > 1) { /* Remove entry from QoS table first */ ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 06/10] net/dpaa2: set default flow miss action per device 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (4 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 05/10] net/dpaa2: support flow drop action Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta ` (4 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> Remove the DPAA2_FLOW_CONTROL_MISS_FLOW environment variable and use the last Rx queue configured in the traffic class as the default flow steering miss queue. Users who relied on the environment variable must use the rte_flow API instead. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- doc/guides/rel_notes/release_26_11.rst | 5 +++++ drivers/net/dpaa2/dpaa2_flow.c | 18 +++++------------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index 934efaaf93..9835d74b17 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -105,6 +105,11 @@ New Features * Added the inner IP header to the RSS hash so tunneled traffic is distributed across the Rx queues. + * Removed ``DPAA2_FLOW_CONTROL_MISS_FLOW`` environment variable. The + flow steering miss queue now defaults to the last Rx queue configured + in the traffic class. Users who previously redirected unmatched + frames to a specific queue via this variable must use the rte_flow + API instead. * **Updated NXP ENETC4 PMD.** diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index f0748081b3..04b6618bbf 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -24,7 +24,6 @@ #include <dpaa2_pmd_logs.h> static char *dpaa2_flow_control_log; -static uint16_t dpaa2_flow_miss_flow_id; /* Default miss flow id is 0. */ static int dpaa2_sp_loaded = -1; enum dpaa2_flow_entry_size { @@ -4589,8 +4588,12 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, if (rss_dist) return 0; + uint16_t nb_rxq = priv->eth_dev->data->nb_rx_queues; + uint16_t first = tc_id * dist_size; + tc_cfg.enable = true; - tc_cfg.fs_miss_flow_id = dpaa2_flow_miss_flow_id; + tc_cfg.fs_miss_flow_id = nb_rxq > first ? + RTE_MIN(dist_size, nb_rxq - first) - 1 : 0; ret = dpni_set_rx_fs_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg); if (ret < 0) { @@ -5224,17 +5227,6 @@ dpaa2_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, dpaa2_flow_control_log = getenv("DPAA2_FLOW_CONTROL_LOG"); - if (getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")) { - dpaa2_flow_miss_flow_id = - (uint16_t)atoi(getenv("DPAA2_FLOW_CONTROL_MISS_FLOW")); - if (dpaa2_flow_miss_flow_id >= priv->dist_queues) { - DPAA2_PMD_ERR("Missed flow ID %d >= dist size(%d)", - dpaa2_flow_miss_flow_id, - priv->dist_queues); - return NULL; - } - } - flow = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_flow), RTE_CACHE_LINE_SIZE); if (!flow) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (5 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 06/10] net/dpaa2: set default flow miss action per device Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 08/10] net/dpaa2: add minimum key size support Prashant Gupta ` (3 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Gagandeep Singh From: Gagandeep Singh <g.singh@nxp.com> For default RSS distribution, the mbuf is marked with RTE_MBUF_F_RX_RSS_HASH and the hash value is taken from the high word of FLC. Configure flow steering actions with FLC enabled to align the stashing settings with the RSS configuration. The TC ID and flow ID are packed into the FLC low word by the hardware. An Rx mbuf received from the FS table has the FS_MARK bit set in the FLC low word; such mbufs are marked with RTE_MBUF_F_RX_FDIR and the TC and flow ID are encoded in hash.fdir.hi. Signed-off-by: Gagandeep Singh <g.singh@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.h | 12 +++++++++ drivers/net/dpaa2/dpaa2_flow.c | 42 ++++++++++++++++++++++++++++++++ drivers/net/dpaa2/dpaa2_rxtx.c | 18 ++++++++++++-- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 149954fb6b..2569b2bd83 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -282,6 +282,18 @@ enum dpaa2_ecpri_fafe_type { /* ECPRI shares SP context with VXLAN*/ #define DPAA2_ECPRI_MSG_OFFSET DPAA2_VXLAN_VNI_OFFSET +#define DPAA2_FS_FLC_FS_MARK_OFFSET \ + (DPAA2_FLC_DATA_STASHING + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_OFFSET \ + (DPAA2_FS_FLC_FS_MARK_OFFSET + DPAA2_FLC_STASHING_MAX_BIT_SIZE) + +#define DPAA2_FS_FLC_TC_BIT_SIZE (sizeof(uint8_t) * 8) +#define DPAA2_FS_FLC_TC_MASK ((1 << DPAA2_FS_FLC_TC_BIT_SIZE) - 1) + +#define DPAA2_FS_FLC_FLOW_OFFSET \ + (DPAA2_FS_FLC_TC_OFFSET + DPAA2_FS_FLC_TC_BIT_SIZE) + #define DPAA2_ECPRI_MAX_EXTRACT_NB 8 struct ipv4_sd_addr_extract_rule { diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 04b6618bbf..28106a033a 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -4383,6 +4383,13 @@ dpaa2_flow_verify_action(struct dpaa2_dev_priv *priv, switch (actions[j].type) { case RTE_FLOW_ACTION_TYPE_QUEUE: dest_queue = actions[j].conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } rxq = priv->rx_vq[dest_queue->index]; if (attr->group != rxq->tc_index) { DPAA2_PMD_ERR("FSQ(%d.%d) not in TC[%d]", @@ -4445,6 +4452,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, struct dpaa2_dev_priv *dest_priv; const struct rte_flow_action_queue *dest_queue; struct dpaa2_queue *dest_q; + uint64_t flc = 0; memset(&flow->fs_action_cfg, 0, sizeof(struct dpni_fs_action_cfg)); @@ -4452,7 +4460,41 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, if (flow->action_type == RTE_FLOW_ACTION_TYPE_QUEUE) { dest_queue = rte_action->conf; + if (dest_queue->index >= MAX_RX_QUEUES || + !priv->rx_vq[dest_queue->index]) { + DPAA2_PMD_ERR("Invalid FSQ index(%d)", + dest_queue->index); + + return -EINVAL; + } dest_q = priv->rx_vq[dest_queue->index]; + if (flow->tc_id != dest_q->tc_index) { + DPAA2_PMD_ERR("RXQ[%d](%d.%d) not in TC[%d]", + dest_queue->index, + dest_q->tc_index, dest_q->flow_id, + flow->tc_id); + + return -EINVAL; + } + flow->fs_action_cfg.options = + DPNI_FS_OPT_SET_FLC | DPNI_FS_OPT_SET_STASH_CONTROL; + + if (dest_q->data_stashing_off) { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 0, &flc); + } else { + dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, + 1, &flc); + } + if ((dpaa2_svr_family & 0xffff0000) != SVR_LX2160A) { + dpaa2_flc_stashing_set(DPAA2_FLC_ANNO_STASHING, + 1, &flc); + } + + flc |= ((uint64_t)1) << DPAA2_FS_FLC_FS_MARK_OFFSET; + flc |= ((uint64_t)dest_q->tc_index) << DPAA2_FS_FLC_TC_OFFSET; + flc |= ((uint64_t)dest_q->flow_id) << DPAA2_FS_FLC_FLOW_OFFSET; + flow->fs_action_cfg.flc = flc; flow->fs_action_cfg.flow_id = dest_q->flow_id; } else if (flow->action_type == RTE_FLOW_ACTION_TYPE_PORT_ID || flow->action_type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT) { diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c31d6556ad..71e292fea6 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -58,6 +58,7 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, uint16_t frc = DPAA2_GET_FD_FRC_PARSE_SUM(fd); struct dpaa2_annot_hdr *annotation = (struct dpaa2_annot_hdr *)hw_annot_addr; + uint32_t flc_lo, tc, flow; if (unlikely(dpaa2_print_parser_result)) dpaa2_print_parse_result(annotation); @@ -118,8 +119,21 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } - m->hash.rss = fd->simple.flc_hi; - m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + flc_lo = fd->simple.flc_lo; + if (flc_lo & (1 << DPAA2_FS_FLC_FS_MARK_OFFSET)) { + tc = (flc_lo >> DPAA2_FS_FLC_TC_OFFSET) & + DPAA2_FS_FLC_TC_MASK; + flow = flc_lo >> DPAA2_FS_FLC_FLOW_OFFSET; + m->ol_flags |= RTE_MBUF_F_RX_FDIR; + m->hash.fdir.hi = (tc << 16) | flow; + DPAA2_PMD_DP_DEBUG("FS frame received from TC[%d]->flow%d", + tc, flow); + } else { + m->hash.rss = fd->simple.flc_hi; + m->ol_flags |= RTE_MBUF_F_RX_RSS_HASH; + DPAA2_PMD_DP_DEBUG("Hash frame received with RSS(%08x)", + m->hash.rss); + } if (dpaa2_enable_ts[m->port]) { *dpaa2_timestamp_dynfield(m) = annotation->word2; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 08/10] net/dpaa2: add minimum key size support 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (6 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta ` (2 subsequent siblings) 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> The default size for a QoS key is 24 bytes. If the key size is smaller than the maximum, use the default (minimum) key size instead of always returning the maximum size (56 bytes). This allows smaller flow tables to be used when the extracted key fits within the default size. Support for 24-byte QoS key entries is available from DPNI version 8.7 onwards. For older DPNI versions, the existing 56-byte entry size is retained to maintain compatibility. Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_flow.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_flow.c b/drivers/net/dpaa2/dpaa2_flow.c index 28106a033a..979ab4cae0 100644 --- a/drivers/net/dpaa2/dpaa2_flow.c +++ b/drivers/net/dpaa2/dpaa2_flow.c @@ -26,8 +26,11 @@ static char *dpaa2_flow_control_log; static int dpaa2_sp_loaded = -1; +/* Default size of a key */ +#define DPNI_DEFAULT_KEY_SIZE 24 + enum dpaa2_flow_entry_size { - DPAA2_FLOW_ENTRY_MIN_SIZE = (DPNI_MAX_KEY_SIZE / 2), + DPAA2_FLOW_ENTRY_MIN_SIZE = DPNI_DEFAULT_KEY_SIZE, DPAA2_FLOW_ENTRY_MAX_SIZE = DPNI_MAX_KEY_SIZE }; @@ -4519,7 +4522,7 @@ dpaa2_configure_flow_fs_action(struct dpaa2_dev_priv *priv, } static inline uint16_t -dpaa2_flow_entry_size(uint16_t key_max_size) +dpaa2_flow_entry_size(struct dpaa2_dev_priv *priv, uint16_t key_max_size) { if (key_max_size > DPAA2_FLOW_ENTRY_MAX_SIZE) { DPAA2_PMD_ERR("Key size(%d) > max(%d)", @@ -4529,11 +4532,11 @@ dpaa2_flow_entry_size(uint16_t key_max_size) return 0; } - if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE) + if (key_max_size > DPAA2_FLOW_ENTRY_MIN_SIZE || + dpaa2_dev_cmp_dpni_ver(priv, 8, 7) < 0) return DPAA2_FLOW_ENTRY_MAX_SIZE; - /* Current MC only support fixed entry size(56)*/ - return DPAA2_FLOW_ENTRY_MAX_SIZE; + return DPAA2_FLOW_ENTRY_MIN_SIZE; } static inline int @@ -4595,7 +4598,7 @@ dpaa2_configure_fs_rss_table(struct dpaa2_dev_priv *priv, } key_max_size = tc_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_fs_extracts_log(priv, tc_id); ret = dpkg_prepare_key_cfg(&tc_extract->dpkg, @@ -4690,7 +4693,7 @@ dpaa2_configure_qos_table(struct dpaa2_dev_priv *priv, } key_max_size = qos_extract->key_profile.key_max_size; - entry_size = dpaa2_flow_entry_size(key_max_size); + entry_size = dpaa2_flow_entry_size(priv, key_max_size); dpaa2_flow_qos_extracts_log(priv); @@ -4981,11 +4984,11 @@ dpaa2_generic_flow_set(struct dpaa2_dev_flow *flow, qos_key_extract = &priv->extract.qos_key_extract; key_size = qos_key_extract->key_profile.key_max_size; - flow->qos_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->qos_rule.key_size = dpaa2_flow_entry_size(priv, key_size); tc_key_extract = &priv->extract.tc_key_extract[flow->tc_id]; key_size = tc_key_extract->key_profile.key_max_size; - flow->fs_rule.key_size = dpaa2_flow_entry_size(key_size); + flow->fs_rule.key_size = dpaa2_flow_entry_size(priv, key_size); /* Let's parse action on matching traffic */ end_of_list = 0; -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (7 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 08/10] net/dpaa2: add minimum key size support Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 10/10] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-20 15:07 ` [PATCH v14-S2 00/10] net/dpaa2 updates Stephen Hemminger 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Hemant Agrawal From: Hemant Agrawal <hemant.agrawal@nxp.com> Extend dpaa2_dev_rx_parse_new() (LX2160A FRC fast path) to identify IPv4/IPv6 fragmented packets, IPsec ESP, and GTP-U/GTP-C packets. Map the corresponding parser summary values to DPDK packet types. Fragmented IPv4/IPv6 packets are reported with RTE_PTYPE_L4_FRAG. GTP-U and GTP-C packets are additionally marked with RTE_PTYPE_L4_UDP to reflect the UDP transport used by the outer tunnel header. Advertise the newly supported packet types through dpaa2_supported_ptypes_get(). Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 4 +++ drivers/net/dpaa2/dpaa2_ethdev.h | 20 ++++++++++++--- drivers/net/dpaa2/dpaa2_rxtx.c | 44 ++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index f88ecb88aa..72b37a988d 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -1371,6 +1371,10 @@ dpaa2_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_TUNNEL_ESP, + RTE_PTYPE_TUNNEL_GTPU, + RTE_PTYPE_TUNNEL_GTPC, }; if (dev->rx_pkt_burst == dpaa2_dev_prefetch_rx || diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index 2569b2bd83..dc72939103 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -127,9 +127,9 @@ #define DPAA2_PKT_TYPE_ETHER 0x0060 #define DPAA2_PKT_TYPE_IPV4 0x0000 #define DPAA2_PKT_TYPE_IPV6 0x0020 -#define DPAA2_PKT_TYPE_IPV4_EXT \ +#define DPAA2_PKT_TYPE_IPV4_FRAG \ (0x0001 | DPAA2_PKT_TYPE_IPV4) -#define DPAA2_PKT_TYPE_IPV6_EXT \ +#define DPAA2_PKT_TYPE_IPV6_FRAG \ (0x0001 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_TCP \ (0x000e | DPAA2_PKT_TYPE_IPV4) @@ -144,9 +144,21 @@ #define DPAA2_PKT_TYPE_IPV6_SCTP \ (0x000f | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_IPV4_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV4_EXT) + (0x0003 | DPAA2_PKT_TYPE_IPV4_FRAG) #define DPAA2_PKT_TYPE_IPV6_ICMP \ - (0x0003 | DPAA2_PKT_TYPE_IPV6_EXT) + (0x0003 | DPAA2_PKT_TYPE_IPV6_FRAG) +#define DPAA2_PKT_TYPE_IPV4_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_ESP \ + (0x0005 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPU \ + (0x0014 | DPAA2_PKT_TYPE_IPV6) +#define DPAA2_PKT_TYPE_IPV4_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV4) +#define DPAA2_PKT_TYPE_IPV6_GTPC \ + (0x0015 | DPAA2_PKT_TYPE_IPV6) #define DPAA2_PKT_TYPE_VLAN_1 0x0160 #define DPAA2_PKT_TYPE_VLAN_2 0x0260 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index 71e292fea6..c2c581f69b 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -76,14 +76,6 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6; break; - case DPAA2_PKT_TYPE_IPV4_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV4_EXT; - break; - case DPAA2_PKT_TYPE_IPV6_EXT: - m->packet_type = RTE_PTYPE_L2_ETHER | - RTE_PTYPE_L3_IPV6_EXT; - break; case DPAA2_PKT_TYPE_IPV4_TCP: m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; @@ -116,6 +108,42 @@ dpaa2_dev_rx_parse_new(struct rte_mbuf *m, const struct qbman_fd *fd, m->packet_type = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; break; + case DPAA2_PKT_TYPE_IPV4_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV6_FRAG: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_FRAG; + break; + case DPAA2_PKT_TYPE_IPV4_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV6_ESP: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_TUNNEL_ESP; + break; + case DPAA2_PKT_TYPE_IPV4_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV6_GTPU: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPU; + break; + case DPAA2_PKT_TYPE_IPV4_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; + case DPAA2_PKT_TYPE_IPV6_GTPC: + m->packet_type = RTE_PTYPE_L2_ETHER | + RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP | + RTE_PTYPE_TUNNEL_GTPC; + break; default: m->packet_type = dpaa2_dev_rx_parse_slow(m, annotation); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* [PATCH v14-S2 10/10] net/dpaa2: rename Rx queue flags 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (8 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta @ 2026-10-20 14:48 ` Prashant Gupta 2026-10-20 15:07 ` [PATCH v14-S2 00/10] net/dpaa2 updates Stephen Hemminger 10 siblings, 0 replies; 356+ messages in thread From: Prashant Gupta @ 2026-10-20 14:48 UTC (permalink / raw) To: stephen, dev; +Cc: Jun Yang From: Jun Yang <jun.yang@nxp.com> Rename the Rx-side device flags to a consistent DPAA2_RX_*_FLAG naming: DPAAX_RX_ERROR_QUEUE_FLAG becomes DPAA2_RX_ERROR_QUEUE_FLAG and DPAA2_DATA_STASHING_OFF becomes DPAA2_RX_DATA_STASHING_OFF_FLAG. This is a mechanical rename with no functional change. Signed-off-by: Jun Yang <jun.yang@nxp.com> --- drivers/net/dpaa2/dpaa2_ethdev.c | 10 +++++----- drivers/net/dpaa2/dpaa2_ethdev.h | 4 ++-- drivers/net/dpaa2/dpaa2_rxtx.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c index 72b37a988d..6afd641709 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.c +++ b/drivers/net/dpaa2/dpaa2_ethdev.c @@ -551,7 +551,7 @@ dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) goto fail; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { priv->rx_err_vq = rte_zmalloc("dpni_rx_err", sizeof(struct dpaa2_queue), 0); if (!priv->rx_err_vq) { @@ -1042,7 +1042,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev, options |= DPNI_QUEUE_OPT_FLC; cfg.flc.stash_control = true; dpaa2_flc_stashing_clear_all(&cfg.flc.value); - if (priv->flags & DPAA2_DATA_STASHING_OFF) { + if (priv->flags & DPAA2_RX_DATA_STASHING_OFF_FLAG) { dpaa2_flc_stashing_set(DPAA2_FLC_DATA_STASHING, 0, &cfg.flc.value); dpaa2_q->data_stashing_off = 1; @@ -1522,7 +1522,7 @@ dpaa2_dev_start(struct rte_eth_dev *dev) dpaa2_q->fqid = qid.fqid; } - if (priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG) { + if (priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG) { ret = dpni_get_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX_ERR, 0, 0, &cfg, &qid); if (ret) { @@ -3476,7 +3476,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) if (dpaa2_get_devargs(dev->devargs, DRIVER_NO_DATA_STASHING) || getenv("DPAA2_DATA_STASHING_OFF")) { - priv->flags |= DPAA2_DATA_STASHING_OFF; + priv->flags |= DPAA2_RX_DATA_STASHING_OFF_FLAG; DPAA2_PMD_INFO("Data stashing disabled"); } @@ -3580,7 +3580,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) } if (dpaa2_get_devargs(dev->devargs, DRIVER_ERROR_QUEUE)) { - priv->flags |= DPAAX_RX_ERROR_QUEUE_FLAG; + priv->flags |= DPAA2_RX_ERROR_QUEUE_FLAG; DPAA2_PMD_INFO("Enable error queue"); } diff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h index dc72939103..d467e7b695 100644 --- a/drivers/net/dpaa2/dpaa2_ethdev.h +++ b/drivers/net/dpaa2/dpaa2_ethdev.h @@ -98,9 +98,9 @@ #define DPAA2_TX_DYNAMIC_CONF_ENABLE RTE_BIT32(9) /* Disable data stashing (prefetch of packet data into CPU cache) */ -#define DPAA2_DATA_STASHING_OFF RTE_BIT32(10) +#define DPAA2_RX_DATA_STASHING_OFF_FLAG RTE_BIT32(10) -#define DPAAX_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) +#define DPAA2_RX_ERROR_QUEUE_FLAG RTE_BIT32(11) /* DPDMUX index for DPMAC */ #define DPAA2_DPDMUX_DPMAC_IDX 0 diff --git a/drivers/net/dpaa2/dpaa2_rxtx.c b/drivers/net/dpaa2/dpaa2_rxtx.c index c2c581f69b..df3eefc134 100644 --- a/drivers/net/dpaa2/dpaa2_rxtx.c +++ b/drivers/net/dpaa2/dpaa2_rxtx.c @@ -829,7 +829,7 @@ dpaa2_dev_prefetch_rx_common(void *queue, struct rte_mbuf **bufs, if (!by_channel) { struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); } @@ -1094,7 +1094,7 @@ dpaa2_dev_rx_common(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts, struct rte_eth_dev_data *eth_data = dpaa2_q->eth_data; struct dpaa2_dev_priv *priv = eth_data->dev_private; - if (!by_channel && unlikely(priv->flags & DPAAX_RX_ERROR_QUEUE_FLAG)) + if (!by_channel && unlikely(priv->flags & DPAA2_RX_ERROR_QUEUE_FLAG)) dump_err_pkts(priv->rx_err_vq); if (by_channel) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 356+ messages in thread
* Re: [PATCH v14-S2 00/10] net/dpaa2 updates 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta ` (9 preceding siblings ...) 2026-10-20 14:48 ` [PATCH v14-S2 10/10] net/dpaa2: rename Rx queue flags Prashant Gupta @ 2026-10-20 15:07 ` Stephen Hemminger 10 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-10-20 15:07 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Tue, 20 Oct 2026 20:18:31 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > Changes in v14: > - Use the last Rx queue configured in each traffic class as > the default flow steering miss queue. > - Update the release note accordingly. Looks good applied to next-net ^ permalink raw reply [flat|nested] 356+ messages in thread
* Re: [PATCH v2 00/47] NXP DPAA2 driver updates and fixes 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta ` (46 preceding siblings ...) 2026-09-10 13:51 ` [PATCH v2 47/47] net/dpaa2: reject Rx queue deferred start Prashant Gupta @ 2026-09-10 16:57 ` Stephen Hemminger 47 siblings, 0 replies; 356+ messages in thread From: Stephen Hemminger @ 2026-09-10 16:57 UTC (permalink / raw) To: Prashant Gupta; +Cc: dev On Thu, 10 Sep 2026 19:21:11 +0530 Prashant Gupta <prashant.gupta_3@nxp.com> wrote: > This series brings the NXP DPAA2 drivers (net, crypto, dma, event, > mempool and the fslmc bus) up to date with the current internal tree. > It carries bug fixes, a reworked flow engine, an extended parser, meter > and policer support, PTP enhancements, and a number of performance > improvements in the Rx/Tx and DQRR handling paths. > > The series is based on commit c1a46b9d9243 and is intended for 26.11. > > Changes in v2: > > - Dropped the header-only patches; every remaining patch now contains > the implementation together with its declarations. > - Addressed all findings reported by checkpatch; the series is clean > against the current checkpatch. > - Removed the per-device Tx scatter/gather pool member that was never > assigned, and used the existing global pool instead. > - Widened the DQRR held-mask shift to 64-bit to avoid undefined > behaviour when the DQRR index exceeds 31. > - Bounded the MAC xstats collection loop by the size of the statistics > array. > - Treated the traffic class priority mask as a bitmask rather than an > index. > - Added a per-entry DQRR consume fallback for portals whose DQRR ring > does not fit the vectored consume encoding. > > Each of the review fixes above has been folded into the patch that > introduced the code in question, so the series remains bisectable. Still get lots of issues when running this through Fable for review. Subject: Re: [PATCH v2 00/47] DPAA2 driver updates Reviewed all 47 patches against upstream main (d55ccd4) and diffed each against its v1 counterpart. Series applies cleanly. Summary: five v1 findings were fixed, two new ones were introduced, and eleven patches still carry the errors reported on v1. Every change in v2 was to something called out in the cover letter or to a one-line site; nothing that required reading a v1 per-patch comment was addressed. Details below, then the process points. Fixed since v1 -------------- 31: sg_mbuf allocated from the global dpaa2_tx_sg_pool (priv member was never assigned); UINT64_C(1) << dqrr_index restored. 35: mac_num bounded by DPAA2_MAC_XSTAT_MAX_NUM. 40: priority_mask = RTE_BIT32(tc_id). 41: vector consume gated to dqrr_size <= 16. Flow engine split into 36 + 37/38/39; the broken "double free on uninit" patch was dropped. AES-GMAC got its string table and note. New in v2 --------- 1: Unrelated hunks squashed into a Cc: stable fix. Besides the GCM change it now carries dpaa2_sec_parse_int() and the drv_dump_mode handler rewrite (patch 6's), fle_sdd_pre_populate() void->int and the long_copy mempool_put (patch 10's), and an unused #include <rte_string_fns.h> in dpaa2_flow.c. Backported as-is it drags dma and net into stable under a crypto tag. 31: struct dpaa2_queue * RTE_ATOMIC(next_txq_to_cnf); Under -Denable_stdatomic=true (the GitHub CI stdatomic job) this expands to _Atomic(next_txq_to_cnf) and does not compile. v1 had RTE_ATOMIC(struct dpaa2_queue *) next_txq_to_cnf; which is right. 32 also dropped v1's rte_atomic_load_explicit() on it. 23/27/32: Regression. The DPAA2_PMD_DEBUG line-buffered dumps from v1 are back to fprintf(rte_log_get_stream(), ...), bypassing log type and level (and a checkpatch forbidden token). 32 also uses %ld for time_t. v1 was correct here. Still open from v1 (errors) --------------------------- 6: Env vars override devargs. dpaa2_sec_get_devargs() is called once per key; whichever key is absent falls to env_set:, which reads both variables and overwrites what the other call took from devargs. Parsing was hardened; the control flow is the same. getenv() in a driver stands. 13: rte_dpaa2_mpool_get_ops_idx() returns 0, not the index, after a successful IPC round trip. mp_req is uninitialised (len_param, num_fds are stack garbage; send_msg() attaches num_fds fds). rte_mp_action_register() failure returns past bp_list/bp_info/ dpbp allocations instead of goto err4. 15: nb_rx_queues/nb_tx_queues are uint8_t; num_rx_tcs * num_queues is truncated before the > MAX_RX_QUEUES check (8 x 32 -> 0). The new fqid != DPAA2_INVALID_FQ_ID early return in rx_queue_setup fires on every reconfigure because rx_queue_release never resets fqid, so new mb_pool/nb_desc/offloads are ignored and the CGID that release cleared is never re-installed. 18: dpaa2_mtr_ops_get() re-initialises priv->meter_lock on every call; rte_mtr_ops_get() invokes it at the start of every rte_mtr_*(). profile/policy delete silently frees meters in use; rte_mtr.h says EBUSY. 23: priv->psr_dynfield_offset is never assigned in 47 patches; priv is zeroed, so dpaa2_dev_rx_parse_offset() writes l3/l4/l5 offsets into mbuf byte 0..2 (buf_addr) on every received packet. Rx timestamp path removed here and not restored until 32; the IEEE1588 build is broken in between (call to a deleted dpaa2_timestamp_dynfield()). The !by_channel guard from upstream 57b8ce0 is still dropped in prefetch_rx_common. 26: num_rx in dpaa2_dev_rx_common() is uint8_t; wraps at 256 while next_pull keeps the loop going. cluster_sdest divides before the zero check. 27: mmap() result tested against NULL, not MAP_FAILED, in scan(), so any host with STRICT_DEVMEM dereferences (void *)-1 at EAL init. 28: dpaa2_eth_eventq_detach() clears DPNI_QUEUE_OPT_DEST before the dpni_set_queue(), so DEST_NONE is never sent and the FQ stays on the DPCON. Taildrop failure in rx_queue_setup returns instead of goto err_free_dpcon. 31: dpaa2_dev_tx_mbuf_to_simple_fd() frees the mbuf on copy failure (goto quit; rte_pktmbuf_free(mbuf)) and dpaa2_dev_tx() then goto send_n_return, returning a count that excludes it; the app retries a freed mbuf. Same shape for the cloned branch, the mid-chain -ENOMEM from no_conf_mbuf_to_sge() (chain already mutated, sg_mbuf leaked), and multi_txq_ordered via send_frames. A per-packet failure is either drop-and-continue or leave-and- return-short, not both. 32: rte_pmd_dpaa2_set_one_step_ts()/get_one_step_ts() (exported experimental, 24.11) deleted from dpaa2_ethdev.c; prototypes remain in installed rte_pmd_dpaa2.h. Link failure, no deprecation. Still open from v1 (warnings, short form) ----------------------------------------- 3: lib/cryptodev hunk should be its own patch; AES-GMAC still advertised in the plain-sym capability table while only the IPsec path accepts it. 7: Byte-identical; PAGE_MASK on the two lines above the new check is still the unvalidated sysconf() value. 8: Byte-identical; the -Warray-bounds it "fixes" is created by patch 11, so Fixes:/Cc: stable are wrong, and 8 KB idxs[4096] per VQ for idxs[0]. 10: Commit message now says rte_panic(); the code returns -ENOMEM. 12: BMT flag applied only when a pooled context is first initialised (sg_entry_post_populate() never writes ctrl.bmt); long-FD path ignores it entirely. New public flag undocumented. 16: dpni version gate is == 8 && >= 7; use dpaa2_dev_cmp_dpni_ver(). Header says 0xF7FF, code returns 0x10000. 23: "No functional change" while packet_type on LX2160A changes. 24: dpaa2_supported_ptypes_get() not updated for any new ptype. 34: Callers moved to V3/V3/V2 MC command ids with no version gate until 36; older MC breaks every flow rule in between. 35: xstats_get_names() returns limit, not the available count, when limit < count. 36: RTE_DPAA2_FLOW_GROUP_TYPE_GET and friends are #ifndef stubs for macros nothing upstream defines; the QoS/FS group paths (and 39's miss-action group handling) are unreachable. getenv() still read on every flow_create(); 13 rte_memcpy() on the control path. Docs: the only change under doc/ in 47 patches is the AES-GMAC note. Missing: three new devargs and a changed drv_tx_conf meaning, mpls/pppoes/geneve/meter/meter_mark in dpaa2.ini, metering, the Removed Items entry for 32. Fold-ins: 33 carries edits to 31's code; 44 cleans up 36; 46 removes the duplicate mc_get_soc_version() that 26 adds. Process ------- The v1 -> v2 delta looks like a re-export from the internal tree with a few fixes applied there, not an edit of the posted series: patch 1 picked up hunks from 6 and 10, three patches lost the logging cleanup v1 had, and 31's atomic declaration went from right to wrong. Working that way means every review comment has to be re-applied twice, and upstream changes under you (57b8ce0 is still lost) have to be re-done each time. Recommendation unchanged: split by tree so the parts that are close can go in. bus/fslmc first, then crypto, dma, mempool and net as separate series, with the Cc: stable fixes at the front of each and containing nothing else. Per-commit builds with -Denable_stdatomic and RTE_LIBRTE_IEEE1588 before posting. Docs with the code, not in a follow-up. ^ permalink raw reply [flat|nested] 356+ messages in thread
end of thread, other threads:[~2026-10-23 15:00 UTC | newest] Thread overview: 356+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-03 13:53 [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Prashant Gupta 2026-09-03 13:53 ` [PATCH 01/45] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta 2026-09-03 13:53 ` [PATCH 02/45] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure Prashant Gupta 2026-09-03 13:53 ` [PATCH 03/45] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta 2026-09-03 13:53 ` [PATCH 04/45] crypto/dpaa2_sec: increase ivsize range for AES-CTR Prashant Gupta 2026-09-03 13:53 ` [PATCH 05/45] crypto/dpaa2_sec: add missing ECN capability Prashant Gupta 2026-09-03 13:53 ` [PATCH 06/45] crypto/dpaa2_sec: add support for env variables Prashant Gupta 2026-09-03 13:53 ` [PATCH 07/45] drivers: fix double free of dpaa2 device on uninit Prashant Gupta 2026-09-03 14:05 ` David Marchand 2026-09-03 13:53 ` [PATCH 08/45] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-09-03 13:53 ` [PATCH 09/45] dma/dpaa2: fix array-bounds warning in dequeue path Prashant Gupta 2026-09-03 13:53 ` [PATCH 10/45] bus/fslmc: defer bus initialization to probe Prashant Gupta 2026-09-03 13:53 ` [PATCH 11/45] dma/dpaa2: validate IOVA in pre-populate helpers Prashant Gupta 2026-09-03 13:53 ` [PATCH 12/45] dma/dpaa2: optimize context index ring enqueue Prashant Gupta 2026-09-03 13:53 ` [PATCH 13/45] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta 2026-09-03 13:53 ` [PATCH 14/45] mempool/dpaa2: support ops index from primary in secondary Prashant Gupta 2026-09-03 13:53 ` [PATCH 15/45] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-09-03 13:53 ` [PATCH 16/45] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta 2026-09-03 13:53 ` [PATCH 17/45] net/dpaa2: support larger burst size Prashant Gupta 2026-09-03 13:53 ` [PATCH 18/45] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-09-03 13:53 ` [PATCH 19/45] net/dpaa2: support meter and policing Prashant Gupta 2026-09-03 13:53 ` [PATCH 20/45] net/dpaa2: support flow drop action Prashant Gupta 2026-09-03 13:53 ` [PATCH 21/45] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-09-03 13:53 ` [PATCH 22/45] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-09-03 13:53 ` [PATCH 23/45] net/dpaa2: add minimum key size support Prashant Gupta 2026-09-03 13:53 ` [PATCH 24/45] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-09-03 13:53 ` [PATCH 25/45] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-09-03 13:53 ` [PATCH 26/45] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-09-03 13:53 ` [PATCH 27/45] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta 2026-09-03 13:53 ` [PATCH 28/45] drivers: identify dpaa2 soft parser protocol Prashant Gupta 2026-09-03 13:53 ` [PATCH 29/45] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta 2026-09-03 13:53 ` [PATCH 30/45] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta 2026-09-03 13:53 ` [PATCH 31/45] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-09-03 13:53 ` [PATCH 32/45] drivers: rework dpaa2 Tx confirmation Prashant Gupta 2026-09-03 13:53 ` [PATCH 33/45] net/dpaa2: ptp enhancements Prashant Gupta 2026-09-03 13:53 ` [PATCH 34/45] net/dpaa2: remove unused soft parser Tx code Prashant Gupta 2026-09-03 13:53 ` [PATCH 35/45] net/dpaa2: update MC dpni QoS and flow steering API Prashant Gupta 2026-09-03 13:53 ` [PATCH 36/45] net/dpaa2: enhance xstat implementation Prashant Gupta 2026-09-03 13:53 ` [PATCH 37/45] net/dpaa2: rework flow engine Prashant Gupta 2026-09-03 13:53 ` [PATCH 38/45] net/dpaa2: support Rx mempool per traffic class Prashant Gupta 2026-09-03 13:53 ` [PATCH 39/45] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta 2026-09-03 13:53 ` [PATCH 40/45] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta 2026-09-03 13:53 ` [PATCH 41/45] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta 2026-09-03 13:53 ` [PATCH 42/45] net/dpaa2: read MC version from device private data Prashant Gupta 2026-09-03 13:53 ` [PATCH 43/45] net/dpaa2: do not overwrite mbuf hash with drop priority Prashant Gupta 2026-09-03 13:53 ` [PATCH 44/45] bus/fslmc: reduce probe-time logging and MC traffic Prashant Gupta 2026-09-03 13:53 ` [PATCH 45/45] net/dpaa2: reject Rx queue deferred start Prashant Gupta 2026-09-07 20:35 ` [PATCH 00/45] net/dpaa2: features and fixes for NXP DPAA2 drivers Stephen Hemminger 2026-09-07 20:47 ` Stephen Hemminger 2026-09-07 21:03 ` Stephen Hemminger 2026-09-07 21:10 ` Stephen Hemminger 2026-09-07 21:22 ` Stephen Hemminger 2026-09-10 13:51 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 01/47] crypto/dpaa2_sec: fix buffer overflow in GCM decrypt Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 02/47] crypto/dpaa2_sec: fix FLE pool leak on sec FD build failure Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 03/47] crypto/dpaa2_sec: support AES-GMAC Prashant Gupta 2026-09-24 10:32 ` [EXTERNAL] " Akhil Goyal 2026-09-10 13:51 ` [PATCH v2 04/47] crypto/dpaa2_sec: increase ivsize range for AES-CTR Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 05/47] crypto/dpaa2_sec: add missing ECN capability Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 06/47] crypto/dpaa2_sec: add support for env variables Prashant Gupta 2026-09-24 10:33 ` [EXTERNAL] " Akhil Goyal 2026-09-10 13:51 ` [PATCH v2 07/47] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 08/47] dma/dpaa2: fix array-bounds warning in dequeue path Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 09/47] bus/fslmc: defer bus initialization to probe Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 10/47] dma/dpaa2: validate IOVA in pre-populate helpers Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 11/47] dma/dpaa2: optimize context index ring enqueue Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 12/47] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 13/47] mempool/dpaa2: support ops index from primary in secondary Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 14/47] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 15/47] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 16/47] net/dpaa2: support larger burst size Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 17/47] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 18/47] net/dpaa2: support meter and policing Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 19/47] net/dpaa2: support flow drop action Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 20/47] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 21/47] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 22/47] net/dpaa2: add minimum key size support Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 23/47] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 24/47] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 25/47] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 26/47] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 27/47] drivers: identify dpaa2 soft parser protocol Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 28/47] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 29/47] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 30/47] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 31/47] drivers: rework dpaa2 Tx confirmation Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 32/47] net/dpaa2: ptp enhancements Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 33/47] net/dpaa2: remove unused soft parser Tx code Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 34/47] net/dpaa2: update MC dpni QoS and flow steering API Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 35/47] net/dpaa2: enhance xstat implementation Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 36/47] net/dpaa2: rework flow engine Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 37/47] net/dpaa2: support GENEVE flow item Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 38/47] net/dpaa2: support flow meter and policer actions Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 39/47] net/dpaa2: support flow table miss actions Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 40/47] net/dpaa2: support Rx mempool per traffic class Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 41/47] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 42/47] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 43/47] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 44/47] net/dpaa2: read MC version from device private data Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 45/47] net/dpaa2: do not overwrite mbuf hash with drop priority Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 46/47] bus/fslmc: reduce probe-time logging and MC traffic Prashant Gupta 2026-09-10 13:51 ` [PATCH v2 47/47] net/dpaa2: reject Rx queue deferred start Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-09-15 11:34 ` [PATCH v3-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-09-15 12:01 ` [PATCH v3-S3 00/10] net/dpaa2: bus, DMA, eventdev and datapath rework Prashant Gupta 2026-09-15 12:01 ` [PATCH v3-S3 01/10] drivers: add dpaa2 DMA bypass memory translation option Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 02/10] drivers: optimize dpaa2 Tx queue and channel mapping Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 03/10] drivers: refresh dpaa2 MC and SoC version info Prashant Gupta 2026-09-17 6:51 ` David Marchand 2026-09-15 12:02 ` [PATCH v3-S3 04/10] drivers: identify dpaa2 soft parser protocol Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 05/10] drivers: assign dpaa2 Rx CGID per traffic class Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 06/10] drivers: inherit dpaa2 rxq config for event queue Prashant Gupta 2026-09-17 6:52 ` David Marchand 2026-09-15 12:02 ` [PATCH v3-S3 07/10] drivers: rework dpaa2 Tx confirmation Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 08/10] drivers: consume dpaa2 DQRR entries in batches Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 09/10] drivers: resolve dpaa2 endpoint in the net driver Prashant Gupta 2026-09-15 12:02 ` [PATCH v3-S3 10/10] drivers: align dpaa2 event port depths with hardware rings Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 00/65] net/dpaa2, event/dpaa2 and fslmc rework Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 01/65] net/dpaa2: refactor and optimize Rx parser result decode Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 02/65] net/dpaa2: generate devargs table and string from one list Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 03/65] crypto/dpaa2_sec: use table-driven devargs parsing Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 04/65] dma/dpaa2: " Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 05/65] net/dpaa2: unify debug dump via log based helpers Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 06/65] net/dpaa2: expose Rx L3/L4/L5 offsets via mbuf dynfield Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 07/65] net/dpaa2: optimize dpaa2 Tx queue and channel mapping Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 08/65] bus/fslmc: split bus-level device walk from VFIO primitives Prashant Gupta 2026-10-23 15:00 ` David Marchand 2026-10-23 13:42 ` [PATCH v4-S3 09/65] bus/fslmc: centralize MC version and SoC detection in the bus layer Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 10/65] net/dpaa2: remove unused soft parser loader Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 11/65] net/dpaa2: cache per-rxq DPNI queue cfg and share CGID per TC Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 12/65] The dpaa2 PMD so far supported only two Tx buffer release schemes: direct release by hardware, and an absolute Tx confirmation mode (drv_tx_conf=1) where every transmitted buffer is returned on a Tx confirmation queue that software must poll to free the buffers. Absolute confirmation adds a confirmation descriptor and a poll cost for all packets, even those the hardware could free on its own Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 13/65] net/dpaa2: support runtime IEEE1588 timestamping Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 14/65] bus/fslmc: consume dpaa2 DQRR entries in batches Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 15/65] bus/fslmc: align dpaa2 event port depths with hardware rings Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 16/65] net/dpaa2: support multi-DPNI FS redirect and QoS table v3 Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 17/65] net/dpaa2: rework xstats with page table and MAC support Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 18/65] net/dpaa2: unify xstats layout and add DPMAC counter struct Prashant Gupta 2026-10-23 13:42 ` [PATCH v4-S3 19/65] net/dpaa2: reimplement xstats_get() on top of xstats_get_by_id() Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 20/65] net/dpaa2: fetch only requested MAC xstats in one MC call Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 21/65] net/dpaa2: rework flow with per-table profile and group types Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 22/65] net/dpaa2: reimplement RSS distribution via rte_flow Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 23/65] net/dpaa2: expand IP address extracts for RSS hashing Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 24/65] net/dpaa2: add policer v2 MC command and L2/L3 byte units Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 25/65] net/dpaa2: support rte_mtr and METER rte_flow action Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 26/65] net/dpaa2: program flow table miss actions via rte_flow Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 27/65] net/dpaa2: support DCB Rx mode " Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 28/65] net/dpaa2: reject Rx queue deferred start Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 29/65] bus/fslmc: support DPCI peer and dynamic queues Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 30/65] bus/fslmc: add alloc/free DPIO API for non-affine portals Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 31/65] event/dpaa2: rework event port model and DPCI handling Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 32/65] event/dpaa2: fix Tx adapter enqueue for mixed destinations Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 33/65] event/dpaa2: rework self test for dynamic link and balance check Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 34/65] event/dpaa2: add DPCON based standalone Rx scheduler Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 35/65] event/dpaa2: add push mode to DPCON " Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 36/65] event/dpaa2: drain Rx scheduler queues on destroy Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 37/65] event/dpaa2: track and detach attached Rx queues Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 38/65] net/dpaa2: add multi-port Tx API Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 39/65] event/dpaa2: limit attached Rx flows per event queue Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 40/65] eventdev: fix port link/unlink callback return documentation Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 41/65] event/dpaa2: allow event queue link to multiple ports Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 42/65] event/dpaa2: report available DPIO count and fix create cleanup Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 43/65] event/dpaa2: use event port DPIO for dequeue wait Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 44/65] bus/fslmc: consolidate DPIO interrupt setup and bound coalescing Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 45/65] event/dpaa2: honor configured dequeue timeout Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 46/65] bus/fslmc: use EAL API for DPIO interrupt Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 47/65] bus/fslmc: defer DPIO interrupt setup and bind portal to worker core Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 48/65] bus/fslmc: move Tx SG mempool to fslmc bus Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 49/65] net/dpaa2: move DPNI endpoint lookup out of the " Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 50/65] net/dpaa2: add APIs to query device info and set default action Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 51/65] net/dpaa2: consolidate dequeue paths and optimize fast path Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 52/65] net/dpaa2: bind per-queue DPIO for rx-queue interrupts Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 53/65] net/dpaa2: add API to clean Tx confirmation queue Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 54/65] event/dpaa2: fix DQRR held buffer accounting on enqueue Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 55/65] bus/fslmc: store dequeue dpio in mbuf seq dynfield Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 56/65] bus/fslmc: use explicit flags for mbuf seqn encoding Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 57/65] net/dpaa2: unify tx burst path for ordered and atomic enqueue Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 58/65] crypto/dpaa2_sec: unify enqueue burst path for ordered enqueue Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 59/65] bus/fslmc: track atomic DCA context per dequeue dpio Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 60/65] bus/fslmc: move enqueue response descriptors to per-queue Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 61/65] event/dpaa2: add ordered schedule type support Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 62/65] bus/fslmc: make DPAA2 ORP/ODP ordering per-queue instead of per-device Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 63/65] event/dpaa2: support multi-port enqueue in selftest random event generator Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 64/65] event/dpaa2: do not fail device creation on DPCI errors Prashant Gupta 2026-10-23 13:43 ` [PATCH v4-S3 65/65] net/dpaa2: add Tx fast path for no-confirmation case Prashant Gupta 2026-09-15 15:42 ` [PATCH v3-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-09-22 9:55 ` [PATCH v4-S2 " Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-09-22 9:55 ` [PATCH v4-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-09-22 13:39 ` [PATCH v4-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-10-01 7:32 ` [PATCH v5-S2 " Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-01 7:32 ` [PATCH v5-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-01 7:33 ` [PATCH v5-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-02 16:42 ` [PATCH v5-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-10-06 15:09 ` [PATCH v6-S2 " Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-06 15:09 ` [PATCH v6-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-06 15:10 ` [PATCH v6-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-07 6:02 ` [PATCH v7-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-07 16:25 ` [PATCH v7-S2 00/13] net/dpaa2: flow, meter and parser features Stephen Hemminger 2026-10-09 10:48 ` [PATCH v8-S2 00/13] net/dpaa2 updates Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-09 10:48 ` [PATCH v8-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-09 10:49 ` [PATCH v8-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-09 19:09 ` [PATCH v8-S2 00/13] net/dpaa2 updates Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 " Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 01/13] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-13 14:52 ` Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 02/13] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 03/13] net/dpaa2: support larger burst size Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 04/13] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-13 14:54 ` Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 05/13] net/dpaa2: support meter and policing Prashant Gupta 2026-10-13 14:55 ` Stephen Hemminger 2026-10-13 14:56 ` Stephen Hemminger 2026-10-13 15:11 ` Stephen Hemminger 2026-10-12 7:04 ` [PATCH v9-S2 06/13] net/dpaa2: support flow drop action Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 07/13] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 08/13] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 09/13] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 10/13] net/dpaa2: restructure dpaa2 parser processing Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 11/13] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 12/13] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-12 7:04 ` [PATCH v9-S2 13/13] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-12 21:22 ` [PATCH v9-S2 00/13] net/dpaa2 updates Stephen Hemminger 2026-10-14 5:43 ` [PATCH v10-S2 00/11] " Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-14 5:43 ` [PATCH v10-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-14 17:18 ` Stephen Hemminger 2026-10-14 5:43 ` [PATCH v10-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-14 5:44 ` [PATCH v10-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 00/11] net/dpaa2 updates Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-15 9:25 ` [PATCH v11-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-15 23:36 ` Stephen Hemminger 2026-10-15 9:25 ` [PATCH v11-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-15 23:26 ` [PATCH v11-S2 00/11] net/dpaa2 updates Stephen Hemminger 2026-10-16 7:03 ` [PATCH v12-S2 " Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 01/11] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 02/11] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 03/11] net/dpaa2: support larger burst size Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 04/11] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 05/11] net/dpaa2: support flow drop action Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 06/11] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 07/11] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 08/11] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 09/11] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-16 7:03 ` [PATCH v12-S2 10/11] net/dpaa2: remove unused soft parser driver Prashant Gupta 2026-10-20 13:45 ` Stephen Hemminger 2026-10-16 7:03 ` [PATCH v12-S2 11/11] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-16 16:18 ` [PATCH v12-S2 00/11] net/dpaa2 updates Stephen Hemminger 2026-10-19 18:34 ` [PATCH v13-S2 00/10] " Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 02/10] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 03/10] net/dpaa2: support larger burst size Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 05/10] net/dpaa2: support flow drop action Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 06/10] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 08/10] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-19 18:34 ` [PATCH v13-S2 10/10] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 00/10] net/dpaa2 updates Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 01/10] net/dpaa2: fix integer overflow in CCSR region mapping Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 02/10] net/dpaa2: set Tx confirmation on device init Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 03/10] net/dpaa2: support larger burst size Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 04/10] net/dpaa2: support MPLS and PPPoE flow distribution Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 05/10] net/dpaa2: support flow drop action Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 06/10] net/dpaa2: set default flow miss action per device Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 07/10] net/dpaa2: identify Rx mbuf hash information by FLC Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 08/10] net/dpaa2: add minimum key size support Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 09/10] net/dpaa2: parse tunnel and fragmented packet types Prashant Gupta 2026-10-20 14:48 ` [PATCH v14-S2 10/10] net/dpaa2: rename Rx queue flags Prashant Gupta 2026-10-20 15:07 ` [PATCH v14-S2 00/10] net/dpaa2 updates Stephen Hemminger 2026-09-10 16:57 ` [PATCH v2 00/47] NXP DPAA2 driver updates and fixes Stephen Hemminger
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox