[v4] lib: set/get max memzone segments

Message ID 20230524222550.3538819-1-ophirmu@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series [v4] lib: set/get max memzone segments |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing fail Unit Testing FAIL
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-abi-testing success Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/github-robot: build success github build: passed
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/iol-testing success Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-x86_64-compile-testing success Testing PASS
ci/iol-unit-testing fail Testing issues
ci/iol-aarch64-compile-testing success Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS

Commit Message

Ophir Munk May 24, 2023, 10:25 p.m. UTC
  Currently, the max memzones count constat (RTE_MAX_MEMZONE) is used to
decide how many memzones a DPDK application can have. This value could
technically be changed by manually editing `rte_config.h` before
compilation, but if DPDK is already compiled, that option is not useful.
There are certain use cases that would benefit from making this value
configurable.

This commit addresses the issue by adding a new API to set the max
number of memzones before EAL initialization (while using the old
constant as default value), as well as an API to get current maximum
number of memzones.

Signed-off-by: Ophir Munk <ophirmu@nvidia.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
---
 app/test/test_func_reentrancy.c     |  2 +-
 app/test/test_malloc_perf.c         |  2 +-
 app/test/test_memzone.c             | 42 ++++++++++++++++++++++++-------------
 config/rte_config.h                 |  1 -
 drivers/net/qede/base/bcm_osal.c    | 38 ++++++++++++++++++++++++++-------
 drivers/net/qede/base/bcm_osal.h    |  3 +++
 drivers/net/qede/qede_main.c        |  7 +++++++
 lib/eal/common/eal_common_memzone.c | 38 ++++++++++++++++++++++++++++++---
 lib/eal/common/eal_memcfg.h         |  2 ++
 lib/eal/include/rte_memzone.h       | 30 ++++++++++++++++++++++++++
 lib/eal/version.map                 |  4 ++++
 11 files changed, 141 insertions(+), 28 deletions(-)
  

Comments

Burakov, Anatoly May 25, 2023, 2:53 p.m. UTC | #1
On 5/24/2023 11:25 PM, Ophir Munk wrote:
> Currently, the max memzones count constat (RTE_MAX_MEMZONE) is used to
> decide how many memzones a DPDK application can have. This value could
> technically be changed by manually editing `rte_config.h` before
> compilation, but if DPDK is already compiled, that option is not useful.
> There are certain use cases that would benefit from making this value
> configurable.
> 
> This commit addresses the issue by adding a new API to set the max
> number of memzones before EAL initialization (while using the old
> constant as default value), as well as an API to get current maximum
> number of memzones.
> 
> Signed-off-by: Ophir Munk <ophirmu@nvidia.com>
> Acked-by: Morten Brørup <mb@smartsharesystems.com>
> ---


> +
> +int
> +rte_memzone_max_set(size_t max)
> +{
> +	struct rte_mem_config *mcfg;
> +
> +	if (eal_get_internal_configuration()->init_complete > 0)
> +		return -1;
> +
> +	mcfg = rte_eal_get_configuration()->mem_config;
> +	if (!mcfg)
> +		return -1;
> +
> +	mcfg->max_memzone = max;
> +
> +	return 0;
> +}

Would this even work? AFAIR mem_config is only available some time 
during EAL init, not before (mem_config pointer will be NULL at that point).

I suggest the following flow:

set():

if init_complete => return -1
else => set local static value

get():

if init_complete => return memzones.count
else => return local static value (set to our default)

That way we don't actually need the memconfig, and multiprocess will 
work because memzones.count is shared between primary and secondary anyway.
  
David Marchand May 26, 2023, 9:55 a.m. UTC | #2
On Thu, May 25, 2023 at 12:26 AM Ophir Munk <ophirmu@nvidia.com> wrote:
>
> Currently, the max memzones count constat (RTE_MAX_MEMZONE) is used to
> decide how many memzones a DPDK application can have. This value could
> technically be changed by manually editing `rte_config.h` before
> compilation, but if DPDK is already compiled, that option is not useful.
> There are certain use cases that would benefit from making this value
> configurable.
>
> This commit addresses the issue by adding a new API to set the max
> number of memzones before EAL initialization (while using the old
> constant as default value), as well as an API to get current maximum
> number of memzones.
>
> Signed-off-by: Ophir Munk <ophirmu@nvidia.com>
> Acked-by: Morten Brørup <mb@smartsharesystems.com>

qede maintainers, can you double check the change on your driver please?
Thanks.
  
Alok Prasad May 28, 2023, 12:09 p.m. UTC | #3
> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: 26 May 2023 15:25
> To: Devendra Singh Rawat <dsinghrawat@marvell.com>; Alok Prasad <palok@marvell.com>
> Cc: dev@dpdk.org; Bruce Richardson <bruce.richardson@intel.com>; Ophir Munk <ophirmu@nvidia.com>; Matan Azrad
> <matan@nvidia.com>; Thomas Monjalon <thomas@monjalon.net>; Lior Margalit <lmargalit@nvidia.com>
> Subject: [EXT] Re: [PATCH v4] lib: set/get max memzone segments
> 
> External Email
> 
> ----------------------------------------------------------------------
> On Thu, May 25, 2023 at 12:26 AM Ophir Munk <ophirmu@nvidia.com> wrote:
> >
> > Currently, the max memzones count constat (RTE_MAX_MEMZONE) is used to
> > decide how many memzones a DPDK application can have. This value could
> > technically be changed by manually editing `rte_config.h` before
> > compilation, but if DPDK is already compiled, that option is not useful.
> > There are certain use cases that would benefit from making this value
> > configurable.
> >
> > This commit addresses the issue by adding a new API to set the max
> > number of memzones before EAL initialization (while using the old
> > constant as default value), as well as an API to get current maximum
> > number of memzones.
> >
> > Signed-off-by: Ophir Munk <ophirmu@nvidia.com>
> > Acked-by: Morten Brørup <mb@smartsharesystems.com>
> 
> qede maintainers, can you double check the change on your driver please?
> Thanks.
> 
> 
> --
> David Marchand

Acked-by: Alok Prasad <palok@marvell.com>
  
Ophir Munk May 30, 2023, 11:37 a.m. UTC | #4
> -----Original Message-----
> Subject: Re: [PATCH v4] lib: set/get max memzone segments
> 
> On 5/24/2023 11:25 PM, Ophir Munk wrote:
> > Currently, the max memzones count constat (RTE_MAX_MEMZONE) is used
> to
> > decide how many memzones a DPDK application can have. This value could
> > technically be changed by manually editing `rte_config.h` before
> > compilation, but if DPDK is already compiled, that option is not useful.
> > There are certain use cases that would benefit from making this value
> > configurable.
> >
> > This commit addresses the issue by adding a new API to set the max
> > number of memzones before EAL initialization (while using the old
> > constant as default value), as well as an API to get current maximum
> > number of memzones.
> >
> > Signed-off-by: Ophir Munk <ophirmu@nvidia.com>
> > Acked-by: Morten Brørup <mb@smartsharesystems.com>
> > ---
> 
> > +
> > +int
> > +rte_memzone_max_set(size_t max)
> > +{
> > +	struct rte_mem_config *mcfg;
> > +
> > +	if (eal_get_internal_configuration()->init_complete > 0)
> > +		return -1;
> > +
> > +	mcfg = rte_eal_get_configuration()->mem_config;
> > +	if (!mcfg)
> > +		return -1;
> > +
> > +	mcfg->max_memzone = max;
> > +
> > +	return 0;
> > +}
> 
> Would this even work? 

Yes. It's working. 
I successfully ran the following test:

int max = rte_memzone_max_get(); 
printf("Max memzone before eal_init: %d\n", max);      // Printing the default max value of 2560
rte_memzone_max_set(1000);
max = rte_memzone_max_get();
printf("Max memzone before eal_init after set to 1000: %d\n", max);    // Printing the new max value of 1000
rte_eal_init(argc, argv); 
rte_memzone_max_set(2000); // Here we fail with -1 since we set after eal init
max = rte_memzone_max_get();
printf("Max memzone after eal_init and after set to 2000: %d\n", max);   // Printing the correct max value of 1000

> AFAIR mem_config is only available some time during
> EAL init, not before (mem_config pointer will be NULL at that point).
> 

Please note that DPDK supports early memory config (lib/eal/common/eal_common_config.c):

/* early configuration structure, when memory config is not mmapped */             
static struct rte_mem_config early_mem_config;  

So max memzone is saved in the early memory and later this memory becomes mapped (shared).

Having said that - I think the current patch is correct.
Please confirm.

> I suggest the following flow:
> 
> set():
> 
> if init_complete => return -1

Also if mem_config is NULL => return -1

> else => set local static value
> 

> get():
> 
> if init_complete => return memzones.count else => return local static value (set
> to our default)
> 
> That way we don't actually need the memconfig, and multiprocess will work
> because memzones.count is shared between primary and secondary anyway.
> 
> --
> Thanks,
> Anatoly
  
Thomas Monjalon May 30, 2023, 1:32 p.m. UTC | #5
25/05/2023 00:25, Ophir Munk:
> --- a/config/rte_config.h
> +++ b/config/rte_config.h
> -#define RTE_MAX_MEMZONE 2560

Good to be able to remove this compilation-time configuration.


> --- a/lib/eal/common/eal_common_memzone.c
> +++ b/lib/eal/common/eal_common_memzone.c
> +#define DEFAULT_MAX_MEMZONE 2560

Maybe add "_COUNT" at the end to make clear it is not about the size of a memzone.
We should add a comment here to explain the meaning of this default:
used until the "set" function is called.


> -		"%s(): Number of requested memzone segments exceeds RTE_MAX_MEMZONE\n",
> -			__func__);
> +		"%s(): Number of requested memzone segments exceeds "
> +		"maximum %u\n", __func__, arr->len);

We should keep "maximum" on the first line to ease "grep" in the code.

> +int
> +rte_memzone_max_set(size_t max)
> +{
> +	struct rte_mem_config *mcfg;
> +
> +	if (eal_get_internal_configuration()->init_complete > 0)
> +		return -1;

An error log would be needed here I think.

> +
> +	mcfg = rte_eal_get_configuration()->mem_config;
> +	if (!mcfg)

Better to use "== NULL" for pointers.

> +		return -1;

Do we need an error log as well?

> +
> +	mcfg->max_memzone = max;
> +
> +	return 0;
> +}
> +
> +size_t
> +rte_memzone_max_get(void)
> +{
> +	struct rte_mem_config *mcfg;
> +
> +	mcfg = rte_eal_get_configuration()->mem_config;
> +	if (!mcfg || !mcfg->max_memzone)

Same comment as above: don't use boolean operator for pointer or value.
 
> +		return DEFAULT_MAX_MEMZONE;
> +
> +	return mcfg->max_memzone;
> +}
> diff --git a/lib/eal/common/eal_memcfg.h b/lib/eal/common/eal_memcfg.h
> index ea013a9..183bb25 100644
> --- a/lib/eal/common/eal_memcfg.h
> +++ b/lib/eal/common/eal_memcfg.h
> @@ -75,6 +75,8 @@ struct rte_mem_config {
>  	/**< TSC rate */
>  
>  	uint8_t dma_maskbits; /**< Keeps the more restricted dma mask. */
> +
> +	size_t max_memzone; /**< maximum allowed allocated memzones. */

Uppercase for first work, and we may remove "allowed"?
Suggestion: "Maximum number of allocated memzones."

[...]
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * Set max memzone value

Add a dot at the end.
Instead of "value", we should mention "number" or "count".

> + *
> + * This function can only be called prior to rte_eal_init().
> + *
> + * @param max
> + *   Maximum number of memzones
> + * @return
> + *  0 on success, -1 otherwise
> + */
> +__rte_experimental
> +int rte_memzone_max_set(size_t max);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * Get the maximum number of memzones.
> + *
> + * @note: The maximum value will not change after calling rte_eal_init().
> + *
> + * @return
> + *   Maximum number of memzones
> + */
> +__rte_experimental
> +size_t rte_memzone_max_get(void);

Good, thank you.
  
Ophir Munk May 31, 2023, 7:56 a.m. UTC | #6
> > --- a/lib/eal/common/eal_common_memzone.c
> > +++ b/lib/eal/common/eal_common_memzone.c
> > +#define DEFAULT_MAX_MEMZONE 2560
> 
> Maybe add "_COUNT" at the end to make clear it is not about the size of a
> memzone.
> We should add a comment here to explain the meaning of this default:
> used until the "set" function is called.
> 
> 

Ack

> > -		"%s(): Number of requested memzone segments exceeds
> RTE_MAX_MEMZONE\n",
> > -			__func__);
> > +		"%s(): Number of requested memzone segments exceeds "
> > +		"maximum %u\n", __func__, arr->len);
> 
> We should keep "maximum" on the first line to ease "grep" in the code.
> 

Ack

> > +int
> > +rte_memzone_max_set(size_t max)
> > +{
> > +	struct rte_mem_config *mcfg;
> > +
> > +	if (eal_get_internal_configuration()->init_complete > 0)
> > +		return -1;
> 
> An error log would be needed here I think.
> 

Ack

> > +
> > +	mcfg = rte_eal_get_configuration()->mem_config;
> > +	if (!mcfg)
> 
> Better to use "== NULL" for pointers.
> 
> > +		return -1;
> 

Ack

> Do we need an error log as well?
> 

Yes. Log was added.

> > +
> > +	mcfg = rte_eal_get_configuration()->mem_config;
> > +	if (!mcfg || !mcfg->max_memzone)
> 
> Same comment as above: don't use boolean operator for pointer or value.
> 

Ack

> > --- a/lib/eal/common/eal_memcfg.h
> > +++ b/lib/eal/common/eal_memcfg.h
> > @@ -75,6 +75,8 @@ struct rte_mem_config {
> >  	/**< TSC rate */
> >
> >  	uint8_t dma_maskbits; /**< Keeps the more restricted dma mask. */
> > +
> > +	size_t max_memzone; /**< maximum allowed allocated memzones.
> */
> 
> Uppercase for first work, and we may remove "allowed"?
> Suggestion: "Maximum number of allocated memzones."
> 

Ack

> [...]
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change without prior notice
> > + *
> > + * Set max memzone value
> 
> Add a dot at the end.
> Instead of "value", we should mention "number" or "count".
> 

Ack
  

Patch

diff --git a/app/test/test_func_reentrancy.c b/app/test/test_func_reentrancy.c
index d1ed5d4..ae9de6f 100644
--- a/app/test/test_func_reentrancy.c
+++ b/app/test/test_func_reentrancy.c
@@ -51,7 +51,7 @@  typedef void (*case_clean_t)(unsigned lcore_id);
 #define MEMPOOL_ELT_SIZE                    (sizeof(uint32_t))
 #define MEMPOOL_SIZE                        (4)
 
-#define MAX_LCORES	(RTE_MAX_MEMZONE / (MAX_ITER_MULTI * 4U))
+#define MAX_LCORES	(rte_memzone_max_get() / (MAX_ITER_MULTI * 4U))
 
 static uint32_t obj_count;
 static uint32_t synchro;
diff --git a/app/test/test_malloc_perf.c b/app/test/test_malloc_perf.c
index ccec43a..9bd1662 100644
--- a/app/test/test_malloc_perf.c
+++ b/app/test/test_malloc_perf.c
@@ -165,7 +165,7 @@  test_malloc_perf(void)
 		return -1;
 
 	if (test_alloc_perf("rte_memzone_reserve", memzone_alloc, memzone_free,
-			NULL, memset_us_gb, RTE_MAX_MEMZONE - 1) < 0)
+			NULL, memset_us_gb, rte_memzone_max_get() - 1) < 0)
 		return -1;
 
 	return 0;
diff --git a/app/test/test_memzone.c b/app/test/test_memzone.c
index c9255e5..f10f4fd 100644
--- a/app/test/test_memzone.c
+++ b/app/test/test_memzone.c
@@ -871,9 +871,17 @@  test_memzone_bounded(void)
 static int
 test_memzone_free(void)
 {
-	const struct rte_memzone *mz[RTE_MAX_MEMZONE + 1];
+	const struct rte_memzone **mz;
 	int i;
 	char name[20];
+	int rc = -1;
+
+	mz = rte_calloc("memzone_test", rte_memzone_max_get() + 1,
+			sizeof(struct rte_memzone *), 0);
+	if (!mz) {
+		printf("Fail allocating memzone test array\n");
+		return rc;
+	}
 
 	mz[0] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone0"), 2000,
 			SOCKET_ID_ANY, 0);
@@ -881,42 +889,42 @@  test_memzone_free(void)
 			SOCKET_ID_ANY, 0);
 
 	if (mz[0] > mz[1])
-		return -1;
+		goto exit_test;
 	if (!rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone0")))
-		return -1;
+		goto exit_test;
 	if (!rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone1")))
-		return -1;
+		goto exit_test;
 
 	if (rte_memzone_free(mz[0])) {
 		printf("Fail memzone free - tempzone0\n");
-		return -1;
+		goto exit_test;
 	}
 	if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone0"))) {
 		printf("Found previously free memzone - tempzone0\n");
-		return -1;
+		goto exit_test;
 	}
 	mz[2] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone2"), 2000,
 			SOCKET_ID_ANY, 0);
 
 	if (mz[2] > mz[1]) {
 		printf("tempzone2 should have gotten the free entry from tempzone0\n");
-		return -1;
+		goto exit_test;
 	}
 	if (rte_memzone_free(mz[2])) {
 		printf("Fail memzone free - tempzone2\n");
-		return -1;
+		goto exit_test;
 	}
 	if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone2"))) {
 		printf("Found previously free memzone - tempzone2\n");
-		return -1;
+		goto exit_test;
 	}
 	if (rte_memzone_free(mz[1])) {
 		printf("Fail memzone free - tempzone1\n");
-		return -1;
+		goto exit_test;
 	}
 	if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone1"))) {
 		printf("Found previously free memzone - tempzone1\n");
-		return -1;
+		goto exit_test;
 	}
 
 	i = 0;
@@ -928,7 +936,7 @@  test_memzone_free(void)
 
 	if (rte_memzone_free(mz[0])) {
 		printf("Fail memzone free - tempzone0\n");
-		return -1;
+		goto exit_test;
 	}
 	mz[0] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone0new"), 0,
 			SOCKET_ID_ANY, 0);
@@ -936,17 +944,21 @@  test_memzone_free(void)
 	if (mz[0] == NULL) {
 		printf("Fail to create memzone - tempzone0new - when MAX memzones were "
 				"created and one was free\n");
-		return -1;
+		goto exit_test;
 	}
 
 	for (i = i - 2; i >= 0; i--) {
 		if (rte_memzone_free(mz[i])) {
 			printf("Fail memzone free - tempzone%d\n", i);
-			return -1;
+			goto exit_test;
 		}
 	}
 
-	return 0;
+	rc = 0;
+
+exit_test:
+	rte_free(mz);
+	return rc;
 }
 
 static int test_memzones_left;
diff --git a/config/rte_config.h b/config/rte_config.h
index 7b8c85e..400e44e 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -34,7 +34,6 @@ 
 #define RTE_MAX_MEM_MB_PER_LIST 32768
 #define RTE_MAX_MEMSEG_PER_TYPE 32768
 #define RTE_MAX_MEM_MB_PER_TYPE 65536
-#define RTE_MAX_MEMZONE 2560
 #define RTE_MAX_TAILQ 32
 #define RTE_LOG_DP_LEVEL RTE_LOG_INFO
 #define RTE_MAX_VFIO_CONTAINERS 64
diff --git a/drivers/net/qede/base/bcm_osal.c b/drivers/net/qede/base/bcm_osal.c
index 2c59397..b5249c6 100644
--- a/drivers/net/qede/base/bcm_osal.c
+++ b/drivers/net/qede/base/bcm_osal.c
@@ -47,10 +47,34 @@  void osal_poll_mode_dpc(osal_int_ptr_t hwfn_cookie)
 }
 
 /* Array of memzone pointers */
-static const struct rte_memzone *ecore_mz_mapping[RTE_MAX_MEMZONE];
+static const struct rte_memzone **ecore_mz_mapping = NULL;
 /* Counter to track current memzone allocated */
 static uint16_t ecore_mz_count;
 
+static uint32_t ref_cnt = 0;
+
+int ecore_mz_mapping_alloc(void)
+{
+	if (__atomic_fetch_add(&ref_cnt, 1, __ATOMIC_RELAXED) == 0) {
+		ecore_mz_mapping = rte_calloc("ecore_mz_map",
+				rte_memzone_max_get(), sizeof(struct rte_memzone *), 0);
+	}
+
+	if (!ecore_mz_mapping)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void ecore_mz_mapping_free(void)
+{
+	if (__atomic_fetch_sub(&ref_cnt, 1, __ATOMIC_RELAXED) - 1 == 0) {
+		if (ecore_mz_mapping)
+			rte_free(ecore_mz_mapping);
+		ecore_mz_mapping = NULL;
+	}
+}
+
 unsigned long qede_log2_align(unsigned long n)
 {
 	unsigned long ret = n ? 1 : 0;
@@ -132,9 +156,9 @@  void *osal_dma_alloc_coherent(struct ecore_dev *p_dev,
 	uint32_t core_id = rte_lcore_id();
 	unsigned int socket_id;
 
-	if (ecore_mz_count >= RTE_MAX_MEMZONE) {
-		DP_ERR(p_dev, "Memzone allocation count exceeds %u\n",
-		       RTE_MAX_MEMZONE);
+	if (ecore_mz_count >= rte_memzone_max_get()) {
+		DP_ERR(p_dev, "Memzone allocation count exceeds %zu\n",
+		       rte_memzone_max_get());
 		*phys = 0;
 		return OSAL_NULL;
 	}
@@ -171,9 +195,9 @@  void *osal_dma_alloc_coherent_aligned(struct ecore_dev *p_dev,
 	uint32_t core_id = rte_lcore_id();
 	unsigned int socket_id;
 
-	if (ecore_mz_count >= RTE_MAX_MEMZONE) {
-		DP_ERR(p_dev, "Memzone allocation count exceeds %u\n",
-		       RTE_MAX_MEMZONE);
+	if (ecore_mz_count >= rte_memzone_max_get()) {
+		DP_ERR(p_dev, "Memzone allocation count exceeds %zu\n",
+		       rte_memzone_max_get());
 		*phys = 0;
 		return OSAL_NULL;
 	}
diff --git a/drivers/net/qede/base/bcm_osal.h b/drivers/net/qede/base/bcm_osal.h
index 67e7f75..97e261d 100644
--- a/drivers/net/qede/base/bcm_osal.h
+++ b/drivers/net/qede/base/bcm_osal.h
@@ -477,4 +477,7 @@  enum dbg_status	qed_dbg_alloc_user_data(struct ecore_hwfn *p_hwfn,
 	qed_dbg_alloc_user_data(p_hwfn, user_data_ptr)
 #define OSAL_DB_REC_OCCURRED(p_hwfn) nothing
 
+int ecore_mz_mapping_alloc(void);
+void ecore_mz_mapping_free(void);
+
 #endif /* __BCM_OSAL_H */
diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c
index 0303903..fd63262 100644
--- a/drivers/net/qede/qede_main.c
+++ b/drivers/net/qede/qede_main.c
@@ -72,6 +72,12 @@  qed_probe(struct ecore_dev *edev, struct rte_pci_device *pci_dev,
 	hw_prepare_params.allow_mdump = false;
 	hw_prepare_params.b_en_pacing = false;
 	hw_prepare_params.epoch = OSAL_GET_EPOCH(ECORE_LEADING_HWFN(edev));
+	rc = ecore_mz_mapping_alloc();
+	if (rc) {
+		DP_ERR(edev, "mem zones array allocation failed\n");
+		return rc;
+	}
+
 	rc = ecore_hw_prepare(edev, &hw_prepare_params);
 	if (rc) {
 		DP_ERR(edev, "hw prepare failed\n");
@@ -722,6 +728,7 @@  static void qed_remove(struct ecore_dev *edev)
 		return;
 
 	ecore_hw_remove(edev);
+	ecore_mz_mapping_free();
 }
 
 static int qed_send_drv_state(struct ecore_dev *edev, bool active)
diff --git a/lib/eal/common/eal_common_memzone.c b/lib/eal/common/eal_common_memzone.c
index a9cd91f..77994b8 100644
--- a/lib/eal/common/eal_common_memzone.c
+++ b/lib/eal/common/eal_common_memzone.c
@@ -22,6 +22,8 @@ 
 #include "eal_private.h"
 #include "eal_memcfg.h"
 
+#define DEFAULT_MAX_MEMZONE 2560
+
 static inline const struct rte_memzone *
 memzone_lookup_thread_unsafe(const char *name)
 {
@@ -81,8 +83,9 @@  memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,
 	/* no more room in config */
 	if (arr->count >= arr->len) {
 		RTE_LOG(ERR, EAL,
-		"%s(): Number of requested memzone segments exceeds RTE_MAX_MEMZONE\n",
-			__func__);
+		"%s(): Number of requested memzone segments exceeds "
+		"maximum %u\n", __func__, arr->len);
+
 		rte_errno = ENOSPC;
 		return NULL;
 	}
@@ -396,7 +399,7 @@  rte_eal_memzone_init(void)
 
 	if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
 			rte_fbarray_init(&mcfg->memzones, "memzone",
-			RTE_MAX_MEMZONE, sizeof(struct rte_memzone))) {
+			rte_memzone_max_get(), sizeof(struct rte_memzone))) {
 		RTE_LOG(ERR, EAL, "Cannot allocate memzone list\n");
 		ret = -1;
 	} else if (rte_eal_process_type() == RTE_PROC_SECONDARY &&
@@ -430,3 +433,32 @@  void rte_memzone_walk(void (*func)(const struct rte_memzone *, void *),
 	}
 	rte_rwlock_read_unlock(&mcfg->mlock);
 }
+
+int
+rte_memzone_max_set(size_t max)
+{
+	struct rte_mem_config *mcfg;
+
+	if (eal_get_internal_configuration()->init_complete > 0)
+		return -1;
+
+	mcfg = rte_eal_get_configuration()->mem_config;
+	if (!mcfg)
+		return -1;
+
+	mcfg->max_memzone = max;
+
+	return 0;
+}
+
+size_t
+rte_memzone_max_get(void)
+{
+	struct rte_mem_config *mcfg;
+
+	mcfg = rte_eal_get_configuration()->mem_config;
+	if (!mcfg || !mcfg->max_memzone)
+		return DEFAULT_MAX_MEMZONE;
+
+	return mcfg->max_memzone;
+}
diff --git a/lib/eal/common/eal_memcfg.h b/lib/eal/common/eal_memcfg.h
index ea013a9..183bb25 100644
--- a/lib/eal/common/eal_memcfg.h
+++ b/lib/eal/common/eal_memcfg.h
@@ -75,6 +75,8 @@  struct rte_mem_config {
 	/**< TSC rate */
 
 	uint8_t dma_maskbits; /**< Keeps the more restricted dma mask. */
+
+	size_t max_memzone; /**< maximum allowed allocated memzones. */
 };
 
 /* update internal config from shared mem config */
diff --git a/lib/eal/include/rte_memzone.h b/lib/eal/include/rte_memzone.h
index 5302caa..13de341 100644
--- a/lib/eal/include/rte_memzone.h
+++ b/lib/eal/include/rte_memzone.h
@@ -305,6 +305,36 @@  void rte_memzone_dump(FILE *f);
 void rte_memzone_walk(void (*func)(const struct rte_memzone *, void *arg),
 		      void *arg);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Set max memzone value
+ *
+ * This function can only be called prior to rte_eal_init().
+ *
+ * @param max
+ *   Maximum number of memzones
+ * @return
+ *  0 on success, -1 otherwise
+ */
+__rte_experimental
+int rte_memzone_max_set(size_t max);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get the maximum number of memzones.
+ *
+ * @note: The maximum value will not change after calling rte_eal_init().
+ *
+ * @return
+ *   Maximum number of memzones
+ */
+__rte_experimental
+size_t rte_memzone_max_get(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/eal/version.map b/lib/eal/version.map
index 51a820d..b52a83c 100644
--- a/lib/eal/version.map
+++ b/lib/eal/version.map
@@ -430,6 +430,10 @@  EXPERIMENTAL {
 	rte_thread_create_control;
 	rte_thread_set_name;
 	__rte_eal_trace_generic_blob;
+
+	# added in 23.07
+	rte_memzone_max_set;
+	rte_memzone_max_get;
 };
 
 INTERNAL {