diff mbox series

[v6,07/13] wifi: ath12k: add support for fixed QMI firmware memory

Message ID 20250225064834.2002499-8-quic_rajkbhag@quicinc.com
State Superseded
Headers show
Series wifi: ath12k: add Ath12k AHB driver support for IPQ5332 | expand

Commit Message

Raj Kumar Bhagat Feb. 25, 2025, 6:48 a.m. UTC
IPQ5332 firmware supports only fixed QMI firmware memory.

Hence, add support to read reserved fixed memory region from
device-tree and provide the reserved memory segments for
firmware to use during QMI firmware memory request.

Note that the ability to set the fixed memory will be introduced in
a subsequent patch. Currently, the flag remains unset by default,
ensuring that existing chipsets are unaffected.

Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.3.1-00130-QCAHKSWPL_SILICONZ-1
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00210-QCAHKSWPL_SILICONZ-1

Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/core.c |  25 ++++
 drivers/net/wireless/ath/ath12k/core.h |   4 +
 drivers/net/wireless/ath/ath12k/hw.c   |   4 +
 drivers/net/wireless/ath/ath12k/hw.h   |   1 +
 drivers/net/wireless/ath/ath12k/qmi.c  | 180 ++++++++++++++++++++++---
 5 files changed, 198 insertions(+), 16 deletions(-)

Comments

kernel test robot Feb. 27, 2025, 7:19 p.m. UTC | #1
Hi Raj,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 13a84b4e7dd5d843dfaa54283adb4bbbe0adee15]

url:    https://github.com/intel-lab-lkp/linux/commits/Raj-Kumar-Bhagat/dt-bindings-net-wireless-describe-the-ath12k-AHB-module-for-IPQ5332/20250225-145536
base:   13a84b4e7dd5d843dfaa54283adb4bbbe0adee15
patch link:    https://lore.kernel.org/r/20250225064834.2002499-8-quic_rajkbhag%40quicinc.com
patch subject: [PATCH v6 07/13] wifi: ath12k: add support for fixed QMI firmware memory
config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20250228/202502280215.J3T7EWeY-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250228/202502280215.J3T7EWeY-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502280215.J3T7EWeY-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/net/wireless/ath/ath12k/qmi.c:11:
   drivers/net/wireless/ath/ath12k/qmi.c: In function 'ath12k_qmi_assign_target_mem_chunk':
>> drivers/net/wireless/ath/ath12k/qmi.c:2677:44: warning: format '%lld' expects argument of type 'long long int', but argument 6 has type 'phys_addr_t' {aka 'unsigned int'} [-Wformat=]
    2677 |                                            "failed to assign mem type %d req size %d avail size %lld\n",
         |                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ......
    2680 |                                            rmem->size);
         |                                            ~~~~~~~~~~
         |                                                |
         |                                                phys_addr_t {aka unsigned int}
   drivers/net/wireless/ath/ath12k/debug.h:69:40: note: in definition of macro 'ath12k_dbg'
      69 |                 __ath12k_dbg(ab, mask, fmt, ##__VA_ARGS__);     \
         |                                        ^~~
   drivers/net/wireless/ath/ath12k/qmi.c:2677:100: note: format string is defined here
    2677 |                                            "failed to assign mem type %d req size %d avail size %lld\n",
         |                                                                                                 ~~~^
         |                                                                                                    |
         |                                                                                                    long long int
         |                                                                                                 %d
   drivers/net/wireless/ath/ath12k/qmi.c:2707:44: warning: format '%lld' expects argument of type 'long long int', but argument 6 has type 'phys_addr_t' {aka 'unsigned int'} [-Wformat=]
    2707 |                                            "failed to assign mem type %d req size %d avail size %lld\n",
         |                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ......
    2710 |                                            bdf_size);
         |                                            ~~~~~~~~
         |                                            |
         |                                            phys_addr_t {aka unsigned int}
   drivers/net/wireless/ath/ath12k/debug.h:69:40: note: in definition of macro 'ath12k_dbg'
      69 |                 __ath12k_dbg(ab, mask, fmt, ##__VA_ARGS__);     \
         |                                        ^~~
   drivers/net/wireless/ath/ath12k/qmi.c:2707:100: note: format string is defined here
    2707 |                                            "failed to assign mem type %d req size %d avail size %lld\n",
         |                                                                                                 ~~~^
         |                                                                                                    |
         |                                                                                                    long long int
         |                                                                                                 %d
   drivers/net/wireless/ath/ath12k/qmi.c:2748:44: warning: format '%lld' expects argument of type 'long long int', but argument 6 has type 'phys_addr_t' {aka 'unsigned int'} [-Wformat=]
    2748 |                                            "failed to assign mem type %d req size %d avail size %lld\n",
         |                                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   ......
    2751 |                                            rmem->size);
         |                                            ~~~~~~~~~~
         |                                                |
         |                                                phys_addr_t {aka unsigned int}
   drivers/net/wireless/ath/ath12k/debug.h:69:40: note: in definition of macro 'ath12k_dbg'
      69 |                 __ath12k_dbg(ab, mask, fmt, ##__VA_ARGS__);     \
         |                                        ^~~
   drivers/net/wireless/ath/ath12k/qmi.c:2748:100: note: format string is defined here
    2748 |                                            "failed to assign mem type %d req size %d avail size %lld\n",
         |                                                                                                 ~~~^
         |                                                                                                    |
         |                                                                                                    long long int
         |                                                                                                 %d


vim +2677 drivers/net/wireless/ath/ath12k/qmi.c

  2659	
  2660	static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab)
  2661	{
  2662		struct reserved_mem *rmem;
  2663		phys_addr_t bdf_size;
  2664		int i, idx, ret;
  2665	
  2666		for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
  2667			switch (ab->qmi.target_mem[i].type) {
  2668			case HOST_DDR_REGION_TYPE:
  2669				rmem = ath12k_core_get_reserved_mem(ab, 0);
  2670				if (!rmem) {
  2671					ret = -ENODEV;
  2672					goto out;
  2673				}
  2674	
  2675				if (rmem->size < ab->qmi.target_mem[i].size) {
  2676					ath12k_dbg(ab, ATH12K_DBG_QMI,
> 2677						   "failed to assign mem type %d req size %d avail size %lld\n",
  2678						   ab->qmi.target_mem[i].type,
  2679						   ab->qmi.target_mem[i].size,
  2680						   rmem->size);
  2681					ret = -EINVAL;
  2682					goto out;
  2683				}
  2684	
  2685				ab->qmi.target_mem[idx].paddr = rmem->base;
  2686				ab->qmi.target_mem[idx].v.ioaddr =
  2687					ioremap(ab->qmi.target_mem[idx].paddr,
  2688						ab->qmi.target_mem[i].size);
  2689				if (!ab->qmi.target_mem[idx].v.ioaddr) {
  2690					ret = -EIO;
  2691					goto out;
  2692				}
  2693				ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
  2694				ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
  2695				idx++;
  2696				break;
  2697			case BDF_MEM_REGION_TYPE:
  2698				rmem = ath12k_core_get_reserved_mem(ab, 0);
  2699				if (!rmem) {
  2700					ret = -ENODEV;
  2701					goto out;
  2702				}
  2703	
  2704				bdf_size = rmem->size - ab->hw_params->bdf_addr_offset;
  2705				if (bdf_size < ab->qmi.target_mem[i].size) {
  2706					ath12k_dbg(ab, ATH12K_DBG_QMI,
  2707						   "failed to assign mem type %d req size %d avail size %lld\n",
  2708						   ab->qmi.target_mem[i].type,
  2709						   ab->qmi.target_mem[i].size,
  2710						   bdf_size);
  2711					ret = -EINVAL;
  2712					goto out;
  2713				}
  2714				ab->qmi.target_mem[idx].paddr =
  2715					rmem->base + ab->hw_params->bdf_addr_offset;
  2716				ab->qmi.target_mem[idx].v.ioaddr =
  2717					ioremap(ab->qmi.target_mem[idx].paddr,
  2718						ab->qmi.target_mem[i].size);
  2719				if (!ab->qmi.target_mem[idx].v.ioaddr) {
  2720					ret = -EIO;
  2721					goto out;
  2722				}
  2723				ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
  2724				ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
  2725				idx++;
  2726				break;
  2727			case CALDB_MEM_REGION_TYPE:
  2728				/* Cold boot calibration is not enabled in Ath12k. Hence,
  2729				 * assign paddr = 0.
  2730				 * Once cold boot calibration is enabled add support to
  2731				 * assign reserved memory from DT.
  2732				 */
  2733				ab->qmi.target_mem[idx].paddr = 0;
  2734				ab->qmi.target_mem[idx].v.ioaddr = NULL;
  2735				ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
  2736				ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
  2737				idx++;
  2738				break;
  2739			case M3_DUMP_REGION_TYPE:
  2740				rmem = ath12k_core_get_reserved_mem(ab, 1);
  2741				if (!rmem) {
  2742					ret = -EINVAL;
  2743					goto out;
  2744				}
  2745	
  2746				if (rmem->size < ab->qmi.target_mem[i].size) {
  2747					ath12k_dbg(ab, ATH12K_DBG_QMI,
  2748						   "failed to assign mem type %d req size %d avail size %lld\n",
  2749						   ab->qmi.target_mem[i].type,
  2750						   ab->qmi.target_mem[i].size,
  2751						   rmem->size);
  2752					ret = -EINVAL;
  2753					goto out;
  2754				}
  2755	
  2756				ab->qmi.target_mem[idx].paddr = rmem->base;
  2757				ab->qmi.target_mem[idx].v.ioaddr =
  2758					ioremap(ab->qmi.target_mem[idx].paddr,
  2759						ab->qmi.target_mem[i].size);
  2760				if (!ab->qmi.target_mem[idx].v.ioaddr) {
  2761					ret = -EIO;
  2762					goto out;
  2763				}
  2764				ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
  2765				ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
  2766				idx++;
  2767				break;
  2768			default:
  2769				ath12k_warn(ab, "qmi ignore invalid mem req type %d\n",
  2770					    ab->qmi.target_mem[i].type);
  2771				break;
  2772			}
  2773		}
  2774		ab->qmi.mem_seg_count = idx;
  2775	
  2776		return 0;
  2777	out:
  2778		ath12k_qmi_free_target_mem_chunk(ab);
  2779		return ret;
  2780	}
  2781
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 0b2dec081c6e..5bd852f9572b 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -612,6 +612,31 @@  u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab)
 	return TARGET_NUM_TIDS(SINGLE);
 }
 
+struct reserved_mem *ath12k_core_get_reserved_mem(struct ath12k_base *ab,
+						  int index)
+{
+	struct device *dev = ab->dev;
+	struct reserved_mem *rmem;
+	struct device_node *node;
+
+	node = of_parse_phandle(dev->of_node, "memory-region", index);
+	if (!node) {
+		ath12k_dbg(ab, ATH12K_DBG_BOOT,
+			   "failed to parse memory-region for index %d\n", index);
+		return NULL;
+	}
+
+	rmem = of_reserved_mem_lookup(node);
+	of_node_put(node);
+	if (!rmem) {
+		ath12k_dbg(ab, ATH12K_DBG_BOOT,
+			   "unable to get memory-region for index %d\n", index);
+		return NULL;
+	}
+
+	return rmem;
+}
+
 static void ath12k_core_stop(struct ath12k_base *ab)
 {
 	ath12k_core_stopped(ab);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 85f0cdce774e..398f76a9d2e4 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -14,6 +14,7 @@ 
 #include <linux/dmi.h>
 #include <linux/ctype.h>
 #include <linux/firmware.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/panic_notifier.h>
 #include <linux/average.h>
 #include "qmi.h"
@@ -239,6 +240,7 @@  enum ath12k_dev_flags {
 	ATH12K_FLAG_EXT_IRQ_ENABLED,
 	ATH12K_FLAG_QMI_FW_READY_COMPLETE,
 	ATH12K_FLAG_FTM_SEGMENTED,
+	ATH12K_FLAG_FIXED_MEM_REGION,
 };
 
 struct ath12k_tx_conf {
@@ -1220,6 +1222,8 @@  u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab);
 u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab);
 
 void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag);
+struct reserved_mem *ath12k_core_get_reserved_mem(struct ath12k_base *ab,
+						  int index);
 
 static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state)
 {
diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c
index 91aecca566a4..b4d5651973b7 100644
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ b/drivers/net/wireless/ath/ath12k/hw.c
@@ -1322,6 +1322,7 @@  static const struct ath12k_hw_params ath12k_hw_params[] = {
 
 		.ce_ie_addr = NULL,
 		.ce_remap = NULL,
+		.bdf_addr_offset = 0,
 	},
 	{
 		.name = "wcn7850 hw2.0",
@@ -1406,6 +1407,7 @@  static const struct ath12k_hw_params ath12k_hw_params[] = {
 
 		.ce_ie_addr = NULL,
 		.ce_remap = NULL,
+		.bdf_addr_offset = 0,
 	},
 	{
 		.name = "qcn9274 hw2.0",
@@ -1486,6 +1488,7 @@  static const struct ath12k_hw_params ath12k_hw_params[] = {
 
 		.ce_ie_addr = NULL,
 		.ce_remap = NULL,
+		.bdf_addr_offset = 0,
 	},
 	{
 		.name = "ipq5332 hw1.0",
@@ -1561,6 +1564,7 @@  static const struct ath12k_hw_params ath12k_hw_params[] = {
 
 		.ce_ie_addr = &ath12k_ce_ie_addr_ipq5332,
 		.ce_remap = &ath12k_ce_remap_ipq5332,
+		.bdf_addr_offset = 0xC00000,
 	},
 };
 
diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
index 6a75af093f31..5123d2f51865 100644
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.h
@@ -229,6 +229,7 @@  struct ath12k_hw_params {
 
 	const struct ce_ie_addr *ce_ie_addr;
 	const struct ce_remap *ce_remap;
+	u32 bdf_addr_offset;
 };
 
 struct ath12k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index 6978200fb79a..dc9626087ceb 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -11,6 +11,8 @@ 
 #include "debug.h"
 #include <linux/of.h>
 #include <linux/firmware.h>
+#include <linux/of_address.h>
+#include <linux/ioport.h>
 
 #define SLEEP_CLOCK_SELECT_INTERNAL_BIT	0x02
 #define HOST_CSTATE_BIT			0x04
@@ -2378,7 +2380,8 @@  int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
 	 * failure to firmware and firmware then request multiple blocks of
 	 * small chunk size memory.
 	 */
-	if (ab->qmi.target_mem_delayed) {
+	if (!test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags) &&
+	    ab->qmi.target_mem_delayed) {
 		delayed = true;
 		ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi delays mem_request %d\n",
 			   ab->qmi.mem_seg_count);
@@ -2442,6 +2445,7 @@  static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
 {
 	struct ath12k_hw_group *ag = ab->ag;
 	struct target_mem_chunk *mlo_chunk;
+	bool fixed_mem;
 
 	lockdep_assert_held(&ag->mutex);
 
@@ -2453,8 +2457,13 @@  static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
 		return;
 	}
 
+	fixed_mem = test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags);
 	mlo_chunk = &ag->mlo_mem.chunk[idx];
-	if (mlo_chunk->v.addr) {
+
+	if (fixed_mem && mlo_chunk->v.ioaddr) {
+		iounmap(mlo_chunk->v.ioaddr);
+		mlo_chunk->v.ioaddr = NULL;
+	} else if (mlo_chunk->v.addr) {
 		dma_free_coherent(ab->dev,
 				  mlo_chunk->size,
 				  mlo_chunk->v.addr,
@@ -2464,7 +2473,10 @@  static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
 
 	mlo_chunk->paddr = 0;
 	mlo_chunk->size = 0;
-	chunk->v.addr = NULL;
+	if (fixed_mem)
+		chunk->v.ioaddr = NULL;
+	else
+		chunk->v.addr = NULL;
 	chunk->paddr = 0;
 	chunk->size = 0;
 }
@@ -2475,19 +2487,24 @@  static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)
 	int i, mlo_idx;
 
 	for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) {
-		if (!ab->qmi.target_mem[i].v.addr)
-			continue;
-
 		if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) {
 			ath12k_qmi_free_mlo_mem_chunk(ab,
 						      &ab->qmi.target_mem[i],
 						      mlo_idx++);
 		} else {
-			dma_free_coherent(ab->dev,
-					  ab->qmi.target_mem[i].prev_size,
-					  ab->qmi.target_mem[i].v.addr,
-					  ab->qmi.target_mem[i].paddr);
-			ab->qmi.target_mem[i].v.addr = NULL;
+			if (test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags) &&
+			    ab->qmi.target_mem[i].v.ioaddr) {
+				iounmap(ab->qmi.target_mem[i].v.ioaddr);
+				ab->qmi.target_mem[i].v.ioaddr = NULL;
+			} else {
+				if (!ab->qmi.target_mem[i].v.addr)
+					continue;
+				dma_free_coherent(ab->dev,
+						  ab->qmi.target_mem[i].prev_size,
+						  ab->qmi.target_mem[i].v.addr,
+						  ab->qmi.target_mem[i].paddr);
+				ab->qmi.target_mem[i].v.addr = NULL;
+			}
 		}
 	}
 
@@ -2640,6 +2657,128 @@  static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
 	return ret;
 }
 
+static int ath12k_qmi_assign_target_mem_chunk(struct ath12k_base *ab)
+{
+	struct reserved_mem *rmem;
+	phys_addr_t bdf_size;
+	int i, idx, ret;
+
+	for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
+		switch (ab->qmi.target_mem[i].type) {
+		case HOST_DDR_REGION_TYPE:
+			rmem = ath12k_core_get_reserved_mem(ab, 0);
+			if (!rmem) {
+				ret = -ENODEV;
+				goto out;
+			}
+
+			if (rmem->size < ab->qmi.target_mem[i].size) {
+				ath12k_dbg(ab, ATH12K_DBG_QMI,
+					   "failed to assign mem type %d req size %d avail size %lld\n",
+					   ab->qmi.target_mem[i].type,
+					   ab->qmi.target_mem[i].size,
+					   rmem->size);
+				ret = -EINVAL;
+				goto out;
+			}
+
+			ab->qmi.target_mem[idx].paddr = rmem->base;
+			ab->qmi.target_mem[idx].v.ioaddr =
+				ioremap(ab->qmi.target_mem[idx].paddr,
+					ab->qmi.target_mem[i].size);
+			if (!ab->qmi.target_mem[idx].v.ioaddr) {
+				ret = -EIO;
+				goto out;
+			}
+			ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
+			ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
+			idx++;
+			break;
+		case BDF_MEM_REGION_TYPE:
+			rmem = ath12k_core_get_reserved_mem(ab, 0);
+			if (!rmem) {
+				ret = -ENODEV;
+				goto out;
+			}
+
+			bdf_size = rmem->size - ab->hw_params->bdf_addr_offset;
+			if (bdf_size < ab->qmi.target_mem[i].size) {
+				ath12k_dbg(ab, ATH12K_DBG_QMI,
+					   "failed to assign mem type %d req size %d avail size %lld\n",
+					   ab->qmi.target_mem[i].type,
+					   ab->qmi.target_mem[i].size,
+					   bdf_size);
+				ret = -EINVAL;
+				goto out;
+			}
+			ab->qmi.target_mem[idx].paddr =
+				rmem->base + ab->hw_params->bdf_addr_offset;
+			ab->qmi.target_mem[idx].v.ioaddr =
+				ioremap(ab->qmi.target_mem[idx].paddr,
+					ab->qmi.target_mem[i].size);
+			if (!ab->qmi.target_mem[idx].v.ioaddr) {
+				ret = -EIO;
+				goto out;
+			}
+			ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
+			ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
+			idx++;
+			break;
+		case CALDB_MEM_REGION_TYPE:
+			/* Cold boot calibration is not enabled in Ath12k. Hence,
+			 * assign paddr = 0.
+			 * Once cold boot calibration is enabled add support to
+			 * assign reserved memory from DT.
+			 */
+			ab->qmi.target_mem[idx].paddr = 0;
+			ab->qmi.target_mem[idx].v.ioaddr = NULL;
+			ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
+			ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
+			idx++;
+			break;
+		case M3_DUMP_REGION_TYPE:
+			rmem = ath12k_core_get_reserved_mem(ab, 1);
+			if (!rmem) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			if (rmem->size < ab->qmi.target_mem[i].size) {
+				ath12k_dbg(ab, ATH12K_DBG_QMI,
+					   "failed to assign mem type %d req size %d avail size %lld\n",
+					   ab->qmi.target_mem[i].type,
+					   ab->qmi.target_mem[i].size,
+					   rmem->size);
+				ret = -EINVAL;
+				goto out;
+			}
+
+			ab->qmi.target_mem[idx].paddr = rmem->base;
+			ab->qmi.target_mem[idx].v.ioaddr =
+				ioremap(ab->qmi.target_mem[idx].paddr,
+					ab->qmi.target_mem[i].size);
+			if (!ab->qmi.target_mem[idx].v.ioaddr) {
+				ret = -EIO;
+				goto out;
+			}
+			ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
+			ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
+			idx++;
+			break;
+		default:
+			ath12k_warn(ab, "qmi ignore invalid mem req type %d\n",
+				    ab->qmi.target_mem[i].type);
+			break;
+		}
+	}
+	ab->qmi.mem_seg_count = idx;
+
+	return 0;
+out:
+	ath12k_qmi_free_target_mem_chunk(ab);
+	return ret;
+}
+
 /* clang stack usage explodes if this is inlined */
 static noinline_for_stack
 int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
@@ -3483,11 +3622,20 @@  static void ath12k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
 			   msg->mem_seg[i].type, msg->mem_seg[i].size);
 	}
 
-	ret = ath12k_qmi_alloc_target_mem_chunk(ab);
-	if (ret) {
-		ath12k_warn(ab, "qmi failed to alloc target memory: %d\n",
-			    ret);
-		return;
+	if (test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags)) {
+		ret = ath12k_qmi_assign_target_mem_chunk(ab);
+		if (ret) {
+			ath12k_warn(ab, "failed to assign qmi target memory: %d\n",
+				    ret);
+			return;
+		}
+	} else {
+		ret = ath12k_qmi_alloc_target_mem_chunk(ab);
+		if (ret) {
+			ath12k_warn(ab, "qmi failed to alloc target memory: %d\n",
+				    ret);
+			return;
+		}
 	}
 
 	ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_REQUEST_MEM, NULL);