From: Jun Yang <[email protected]> Add a big-endian hardware buffer descriptor overlay (struct bm_hw_buf_desc) to the bm_buffer union so a release or acquire entry can be built and parsed through one 8-byte access instead of separate 16-bit and 32-bit address halves.
bm_buffer_set64_to_be() writes the whole descriptor in a single store, which also clears the reserved byte and the bpid so no uninitialised stack content reaches the hardware ring, and bm_buffer_get64_from_be() reads the address back. MAX_U48 and U48_BY_HI16_LO32 move from bman.c to fsl_bman.h for the new accessors, and bman_hw_extract_addr() is dropped in favour of bm_buffer_get64_from_be(). In the release ring, bufs[0] overlaps the verb that bm_rcr_pvb_commit() writes last to publish the entry, so only the bpid and the address of the first buffer are stored there; the rest are copied in one memcpy. Signed-off-by: Jun Yang <[email protected]> --- drivers/bus/dpaa/base/qbman/bman.c | 58 ++++++++--------------------- drivers/bus/dpaa/include/fsl_bman.h | 48 ++++++++++++++++++++---- 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/drivers/bus/dpaa/base/qbman/bman.c b/drivers/bus/dpaa/base/qbman/bman.c index 0ae1160973..24b6e92363 100644 --- a/drivers/bus/dpaa/base/qbman/bman.c +++ b/drivers/bus/dpaa/base/qbman/bman.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2008-2016 Freescale Semiconductor Inc. - * Copyright 2017, 2024 NXP + * Copyright 2017, 2024-2026 NXP * */ #include <rte_memcpy.h> @@ -17,20 +17,6 @@ #define IRQNAME "BMan portal %d" #define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */ - -#define MAX_U16 UINT16_MAX -#define MAX_U32 UINT32_MAX -#ifndef BIT_SIZE -#define BIT_SIZE(t) (sizeof(t) * 8) -#endif -#define MAX_U48 \ - ((((uint64_t)MAX_U16) << BIT_SIZE(uint32_t)) | MAX_U32) -#define HI16_OF_U48(x) \ - (((x) >> BIT_SIZE(rte_be32_t)) & MAX_U16) -#define LO32_OF_U48(x) ((x) & MAX_U32) -#define U48_BY_HI16_LO32(hi, lo) \ - (((hi) << BIT_SIZE(uint32_t)) | (lo)) - struct bman_portal { struct bm_portal p; /* 2-element array. pools[0] is mask, pools[1] is snapshot. */ @@ -281,7 +267,7 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs, struct bm_rcr_entry *r; uint8_t i, avail; uint64_t bpid = pool->params.bpid; - struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX]; + struct bm_buffer bm_bufs[FSL_BM_BURST_MAX]; #ifdef RTE_LIBRTE_DPAA_HWDEBUG if (!num || (num > FSL_BM_BURST_MAX)) @@ -298,19 +284,18 @@ bman_release_fast(struct bman_pool *pool, const uint64_t *bufs, if (unlikely(!r)) return -EBUSY; - /* - * we can copy all but the first entry, as this can trigger badness - * with the valid-bit - */ - bm_bufs[0].bpid = bpid; - bm_bufs[0].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[0])); - bm_bufs[0].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[0])); - for (i = 1; i < num; i++) { - bm_bufs[i].hi_addr = cpu_to_be16(HI16_OF_U48(bufs[i])); - bm_bufs[i].lo_addr = cpu_to_be32(LO32_OF_U48(bufs[i])); - } + for (i = 0; i < num; i++) + bm_buffer_set64_to_be(&bm_bufs[i], bufs[i]); - memcpy(r->bufs, bm_bufs, sizeof(struct bm_buffer) * num); + /* bufs[0] overlaps the verb, which bm_rcr_pvb_commit() writes last + * to publish the entry, so do not store over byte 0 here. + */ + r->bpid = bpid; + r->bufs[0].be_desc.hi = bm_bufs[0].be_desc.hi; + r->bufs[0].be_desc.lo = bm_bufs[0].be_desc.lo; + if (num > 1) + memcpy(&r->bufs[1], &bm_bufs[1], + sizeof(struct bm_buffer) * (num - 1)); bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE | (num & BM_RCR_VERB_BUFCOUNT_MASK)); @@ -368,16 +353,6 @@ __rte_unused bman_extract_addr(struct bm_buffer *buf) return buf->addr; } -static inline uint64_t -bman_hw_extract_addr(struct bm_hw_buf_desc *buf) -{ - uint64_t hi, lo; - - hi = be16_to_cpu(buf->hi_addr); - lo = be32_to_cpu(buf->lo_addr); - return U48_BY_HI16_LO32(hi, lo); -} - RTE_EXPORT_INTERNAL_SYMBOL(bman_acquire_fast) int bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num) @@ -386,7 +361,7 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num) struct bm_mc_command *mcc; struct bm_mc_result *mcr; uint8_t i, rst; - struct bm_hw_buf_desc bm_bufs[FSL_BM_BURST_MAX]; + struct bm_buffer bm_bufs[FSL_BM_BURST_MAX]; #ifdef RTE_LIBRTE_DPAA_HWDEBUG if (!num || (num > FSL_BM_BURST_MAX)) @@ -405,11 +380,10 @@ bman_acquire_fast(struct bman_pool *pool, uint64_t *bufs, uint8_t num) if (unlikely(rst < 1 || rst > FSL_BM_BURST_MAX)) return -EINVAL; - rte_memcpy(bm_bufs, mcr->acquire.bufs, - sizeof(struct bm_buffer) * rst); + rte_memcpy(bm_bufs, mcr->acquire.bufs, sizeof(struct bm_buffer) * rst); for (i = 0; i < rst; i++) - bufs[i] = bman_hw_extract_addr(&bm_bufs[i]); + bufs[i] = bm_buffer_get64_from_be(&bm_bufs[i]); return rst; } diff --git a/drivers/bus/dpaa/include/fsl_bman.h b/drivers/bus/dpaa/include/fsl_bman.h index 88e4df503f..fcf2f25257 100644 --- a/drivers/bus/dpaa/include/fsl_bman.h +++ b/drivers/bus/dpaa/include/fsl_bman.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 * * Copyright 2008-2012 Freescale Semiconductor, Inc. - * Copyright 2024 NXP + * Copyright 2024-2026 NXP * */ @@ -47,6 +47,13 @@ struct bm_mc_result; /* MC result */ * pool id specific to this buffer is needed (BM_RCR_VERB_CMD_BPID_MULTI, * BM_MCC_VERB_ACQUIRE), the 'bpid' field is used. */ +struct __rte_packed_begin bm_hw_buf_desc { + uint8_t rsv; + uint8_t bpid; + rte_be16_t hi; /* High 16-bits of 48-bit address */ + rte_be32_t lo; /* Low 32-bits of 48-bit address */ +} __rte_packed_end; + struct __rte_aligned(8) bm_buffer { union { struct { @@ -71,17 +78,11 @@ struct __rte_aligned(8) bm_buffer { u64 __notaddress:16; #endif }; + struct bm_hw_buf_desc be_desc; u64 opaque; }; }; -struct __rte_packed_begin bm_hw_buf_desc { - uint8_t rsv; - uint8_t bpid; - rte_be16_t hi_addr; /* High 16-bits of 48-bit address */ - rte_be32_t lo_addr; /* Low 32-bits of 48-bit address */ -} __rte_packed_end; - static inline u64 bm_buffer_get64(const struct bm_buffer *buf) { return buf->addr; @@ -92,6 +93,14 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf) return (dma_addr_t)buf->addr; } +#ifndef BIT_SIZE +#define BIT_SIZE(t) (sizeof(t) * 8) +#endif +#define MAX_U48 \ + ((((uint64_t)UINT16_MAX) << BIT_SIZE(uint32_t)) | UINT32_MAX) +#define U48_BY_HI16_LO32(hi, lo) \ + (((uint64_t)(hi) << BIT_SIZE(uint32_t)) | (lo)) + #define bm_buffer_set64(buf, v) \ do { \ struct bm_buffer *__buf931 = (buf); \ @@ -99,6 +108,29 @@ static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf) __buf931->lo = lower_32_bits(v); \ } while (0) +/* + * Write the whole 8-byte descriptor in one store. Besides the 48-bit + * address this clears the reserved byte and the bpid field, so no + * uninitialized stack content can be published to the hardware ring. + * Callers that need a bpid must set it after this macro. + */ +#define bm_buffer_set64_to_be(buf, v) \ + do { \ + struct bm_buffer *__buf931 = (buf); \ + \ + __buf931->opaque = cpu_to_be64((uint64_t)(v) & MAX_U48); \ + } while (0) + +#define bm_buffer_get64_from_be(buf) \ + ({ \ + uint64_t hi, lo; \ + struct bm_buffer *__buf931 = (buf); \ + \ + hi = be16_to_cpu(__buf931->be_desc.hi); \ + lo = be32_to_cpu(__buf931->be_desc.lo); \ + U48_BY_HI16_LO32(hi, lo); \ + }) + #define FSL_BM_BURST_MAX 8 /* See 1.5.3.5.4: "Release Command" */ -- 2.25.1

