Message ID | 20250130043508.1885026-8-quic_rajkbhag@quicinc.com |
---|---|
State | New |
Headers | show |
Series | wifi: ath12k: add Ath12k AHB driver support for IPQ5332 | expand |
On 1/30/2025 1:16 PM, Krzysztof Kozlowski wrote: > On 30/01/2025 05:35, Raj Kumar Bhagat wrote: >> @@ -2646,6 +2663,136 @@ 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 device_node *mem_node; >> + struct resource res, m3_res; >> + u32 bdf_start_addr; >> + 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: >> + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); > > > Why cannot you use existing API for reserved memory - > of_reserved_mem_lookup()? > The of_reserved_mem_lookup() requires reserved memory node to read the memory and return in the structure "struct reserved_mem". The of_reserved_mem_lookup() would be used after we get the reserved memory node using the API - ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); In next version we would use of_reserved_mem_lookup(), Something like below: mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); struct reserved_mem res = of_reserved_mem_lookup(mem_node)
On 03/02/2025 10:44, Raj Kumar Bhagat wrote: > On 1/30/2025 1:16 PM, Krzysztof Kozlowski wrote: >> On 30/01/2025 05:35, Raj Kumar Bhagat wrote: >>> @@ -2646,6 +2663,136 @@ 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 device_node *mem_node; >>> + struct resource res, m3_res; >>> + u32 bdf_start_addr; >>> + 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: >>> + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >> >> >> Why cannot you use existing API for reserved memory - >> of_reserved_mem_lookup()? >> > > The of_reserved_mem_lookup() requires reserved memory node to read the memory and > return in the structure "struct reserved_mem". > > The of_reserved_mem_lookup() would be used after we get the reserved memory node > using the API - ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); > > In next version we would use of_reserved_mem_lookup(), Something like below: > mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); Then why do you need ath12k_core_get_reserved_mem_by_name() in the first place? Just use of_reserved_mem_lookup() directly. Why do you need to parse phandle before of_reserved_mem_lookup()? > struct reserved_mem res = of_reserved_mem_lookup(mem_node) Best regards, Krzysztof
On 2/3/2025 3:42 PM, Krzysztof Kozlowski wrote: > On 03/02/2025 10:44, Raj Kumar Bhagat wrote: >> On 1/30/2025 1:16 PM, Krzysztof Kozlowski wrote: >>> On 30/01/2025 05:35, Raj Kumar Bhagat wrote: >>>> @@ -2646,6 +2663,136 @@ 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 device_node *mem_node; >>>> + struct resource res, m3_res; >>>> + u32 bdf_start_addr; >>>> + 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: >>>> + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >>> >>> >>> Why cannot you use existing API for reserved memory - >>> of_reserved_mem_lookup()? >>> >> >> The of_reserved_mem_lookup() requires reserved memory node to read the memory and >> return in the structure "struct reserved_mem". >> >> The of_reserved_mem_lookup() would be used after we get the reserved memory node >> using the API - ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >> >> In next version we would use of_reserved_mem_lookup(), Something like below: >> mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); > > Then why do you need ath12k_core_get_reserved_mem_by_name() in the first > place? Just use of_reserved_mem_lookup() directly. Why do you need to > parse phandle before of_reserved_mem_lookup()? > Sorry, I'm having difficulty understanding this. We have the WiFi node at ab->dev->of_node, but we don't have a node for the reserved-memory 'q6-region'. The of_reserved_mem_lookup() function requires the device node for 'q6-region'. Could you please suggest how we can use of_reserved_mem_lookup() without obtaining the 'q6-region' node first.
On 04/02/2025 10:06, Raj Kumar Bhagat wrote: > On 2/3/2025 3:42 PM, Krzysztof Kozlowski wrote: >> On 03/02/2025 10:44, Raj Kumar Bhagat wrote: >>> On 1/30/2025 1:16 PM, Krzysztof Kozlowski wrote: >>>> On 30/01/2025 05:35, Raj Kumar Bhagat wrote: >>>>> @@ -2646,6 +2663,136 @@ 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 device_node *mem_node; >>>>> + struct resource res, m3_res; >>>>> + u32 bdf_start_addr; >>>>> + 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: >>>>> + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >>>> >>>> >>>> Why cannot you use existing API for reserved memory - >>>> of_reserved_mem_lookup()? >>>> >>> >>> The of_reserved_mem_lookup() requires reserved memory node to read the memory and >>> return in the structure "struct reserved_mem". >>> >>> The of_reserved_mem_lookup() would be used after we get the reserved memory node >>> using the API - ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >>> >>> In next version we would use of_reserved_mem_lookup(), Something like below: >>> mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >> >> Then why do you need ath12k_core_get_reserved_mem_by_name() in the first >> place? Just use of_reserved_mem_lookup() directly. Why do you need to >> parse phandle before of_reserved_mem_lookup()? >> > > Sorry, I'm having difficulty understanding this. > We have the WiFi node at ab->dev->of_node, but we don't have a node for the reserved-memory > 'q6-region'. The of_reserved_mem_lookup() function requires the device node for 'q6-region'. > > Could you please suggest how we can use of_reserved_mem_lookup() without obtaining the > 'q6-region' node first. Hm, it seems you are not using it for this device, so indeed you need to parse phandle. You can still code it simpler - of_property_match_string() is not necessary and of_address_to_resource()+of_node_put() could be in the ath12k_core_get_reserved_mem() Best regards, Krzysztof
On 2/5/2025 2:37 PM, Krzysztof Kozlowski wrote: > On 04/02/2025 10:06, Raj Kumar Bhagat wrote: >> On 2/3/2025 3:42 PM, Krzysztof Kozlowski wrote: >>> On 03/02/2025 10:44, Raj Kumar Bhagat wrote: >>>> On 1/30/2025 1:16 PM, Krzysztof Kozlowski wrote: >>>>> On 30/01/2025 05:35, Raj Kumar Bhagat wrote: >>>>>> @@ -2646,6 +2663,136 @@ 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 device_node *mem_node; >>>>>> + struct resource res, m3_res; >>>>>> + u32 bdf_start_addr; >>>>>> + 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: >>>>>> + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >>>>> >>>>> >>>>> Why cannot you use existing API for reserved memory - >>>>> of_reserved_mem_lookup()? >>>>> >>>> >>>> The of_reserved_mem_lookup() requires reserved memory node to read the memory and >>>> return in the structure "struct reserved_mem". >>>> >>>> The of_reserved_mem_lookup() would be used after we get the reserved memory node >>>> using the API - ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >>>> >>>> In next version we would use of_reserved_mem_lookup(), Something like below: >>>> mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); >>> >>> Then why do you need ath12k_core_get_reserved_mem_by_name() in the first >>> place? Just use of_reserved_mem_lookup() directly. Why do you need to >>> parse phandle before of_reserved_mem_lookup()? >>> >> >> Sorry, I'm having difficulty understanding this. >> We have the WiFi node at ab->dev->of_node, but we don't have a node for the reserved-memory >> 'q6-region'. The of_reserved_mem_lookup() function requires the device node for 'q6-region'. >> >> Could you please suggest how we can use of_reserved_mem_lookup() without obtaining the >> 'q6-region' node first. > > > Hm, it seems you are not using it for this device, so indeed you need to > parse phandle. You can still code it simpler - > of_property_match_string() is not necessary and > of_address_to_resource()+of_node_put() could be in the > ath12k_core_get_reserved_mem() > Thanks, will make it simpler.
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 60c077b016b4..cbe4d6274768 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -609,6 +609,30 @@ u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab) return TARGET_NUM_TIDS(SINGLE); } +struct device_node *ath12k_core_get_reserved_mem_by_name(struct ath12k_base *ab, + const char *name) +{ + struct device *dev = ab->dev; + struct device_node *mem_np; + int index; + + index = of_property_match_string(dev->of_node, "memory-region-names", name); + if (index < 0) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "memory region %s not found\n", name); + return NULL; + } + + mem_np = of_parse_phandle(dev->of_node, "memory-region", index); + if (!mem_np) { + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "failed to parse memory region %s\n", name); + return NULL; + } + + return mem_np; +} + 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 22ade838b99f..fa2eadd60c44 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -239,6 +239,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 { @@ -1203,6 +1204,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 device_node *ath12k_core_get_reserved_mem_by_name(struct ath12k_base *ab, + const char *name); 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 3d1f5309c962..d75769ae03bb 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 @@ -2384,7 +2386,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); @@ -2448,6 +2451,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); @@ -2459,8 +2463,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, @@ -2470,7 +2479,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; } @@ -2481,19 +2493,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; + } } } @@ -2646,6 +2663,136 @@ 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 device_node *mem_node; + struct resource res, m3_res; + u32 bdf_start_addr; + 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: + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); + if (!mem_node || of_address_to_resource(mem_node, 0, &res)) { + ath12k_dbg(ab, ATH12K_DBG_QMI, + "q6-region is not defined in device-tree\n"); + ret = -ENODEV; + goto out; + } + of_node_put(mem_node); + + if (res.end - res.start + 1 < 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, + (res.end - res.start + 1)); + ret = -EINVAL; + goto out; + } + + ab->qmi.target_mem[idx].paddr = res.start; + 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: + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "q6-region"); + if (!mem_node || of_address_to_resource(mem_node, 0, &res)) { + ath12k_dbg(ab, ATH12K_DBG_QMI, + "q6-region is not defined to calculate BDF mem in DT\n"); + ret = -ENODEV; + goto out; + } + of_node_put(mem_node); + + bdf_start_addr = res.start + ab->hw_params->bdf_addr_offset; + if (res.end - bdf_start_addr + 1 < 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, + (res.end - bdf_start_addr + 1)); + ret = -EINVAL; + goto out; + } + ab->qmi.target_mem[idx].paddr = bdf_start_addr; + 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: + mem_node = ath12k_core_get_reserved_mem_by_name(ab, "m3-dump"); + if (!mem_node || of_address_to_resource(mem_node, 0, &m3_res)) { + ath12k_err(ab, "m3_dump not defined in device-tree\n"); + ret = -EINVAL; + goto out; + } + of_node_put(mem_node); + + if (m3_res.end - m3_res.start + 1 < 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, + (m3_res.end - m3_res.start + 1)); + ret = -EINVAL; + goto out; + } + + ab->qmi.target_mem[idx].paddr = m3_res.start; + 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) @@ -3480,11 +3627,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);
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 | 24 ++++ drivers/net/wireless/ath/ath12k/core.h | 3 + drivers/net/wireless/ath/ath12k/hw.c | 4 + drivers/net/wireless/ath/ath12k/hw.h | 1 + drivers/net/wireless/ath/ath12k/qmi.c | 188 ++++++++++++++++++++++--- 5 files changed, 204 insertions(+), 16 deletions(-)