Re: [PATCH ath-next] wifi: ath12k: add support to load shared firmware on multiPD
Vasanthakumar Thiagarajan <[email protected]>
| Newsgroups | org.infradead.lists.ath12k,org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <[email protected]> |
On 8/11/2026 11:13 AM, Aaradhana Sahu wrote: > IPQ5332 platform uses a MultiPD architecture where multiple firmware > instances share common read-only code segments. The driver currently > loads only the per-UserPD firmware, which leaves the shared read-only > firmware unloaded. > > Add support for loading the shared read-only firmware once before the > UserPDs are powered up. The shared segment contains common code that is > identical across all UserPDs and reduces the total firmware memory > requirement. > > Store the reserved memory mapping in struct ath12k_ahb_rproc_info so it can > be shared by all UserPDs and mapped only once. Keep the mapping valid > across UserPD power cycles, and unmap it when the last UserPD is removed. > > Shut down the shared firmware from the rproc deconfiguration path when the > last UserPD is removed. > > Also, pass NULL for the reloc_base parameter because the driver uses fixed > memory regions configured through device tree and does not need the > adjusted physical address after relocation. > > Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.6-01275-QCAHKSWPL_SILICONZ-1 > > Signed-off-by: Aaradhana Sahu <[email protected]> > --- > drivers/net/wireless/ath/ath12k/ahb.c | 166 +++++++++++++++++--- > drivers/net/wireless/ath/ath12k/ahb.h | 9 ++ > drivers/net/wireless/ath/ath12k/wifi7/ahb.c | 3 + > 3 files changed, 157 insertions(+), 21 deletions(-) > > diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c > index 0fc55c9169e1..3985f4e1c067 100644 > --- a/drivers/net/wireless/ath/ath12k/ahb.c > +++ b/drivers/net/wireless/ath/ath12k/ahb.c > @@ -347,35 +347,60 @@ static void ath12k_ahb_stop(struct ath12k_base *ab) > ath12k_ce_cleanup_pipes(ab); > } > > +static int ath12k_ahb_get_fw_load_region(struct ath12k_base *ab) > +{ > + struct ath12k_ahb *ab_ahb = ath12k_ab_to_ahb(ab); > + struct ath12k_ahb_rproc_info *rproc_info = ab_ahb->rproc_info; > + struct device *dev = ab->dev; > + struct resource res; > + int ret; > + > + if (rproc_info->mem_region) > + return 0; > + > + ret = of_reserved_mem_region_to_resource_byname(dev->of_node, "q6-region", &res); > + if (ret) > + return ret; > + > + rproc_info->mem_phys = res.start; > + rproc_info->mem_size = resource_size(&res); > + rproc_info->mem_region = memremap(rproc_info->mem_phys, rproc_info->mem_size, > + MEMREMAP_WC); > + if (!rproc_info->mem_region) { > + ath12k_err(ab, "unable to map memory region: %pa+%zx\n", > + &res.start, rproc_info->mem_size); > + rproc_info->mem_phys = 0; > + rproc_info->mem_size = 0; > + return -ENOMEM; > + } > + > + return 0; > +} > + > +static void ath12k_ahb_put_fw_load_region(struct ath12k_ahb_rproc_info *rproc_info) > +{ > + memunmap(rproc_info->mem_region); > + rproc_info->mem_region = NULL; > + rproc_info->mem_phys = 0; > + rproc_info->mem_size = 0; > +} > + > static int ath12k_ahb_power_up(struct ath12k_base *ab) > { > struct ath12k_ahb *ab_ahb = ath12k_ab_to_ahb(ab); > + struct ath12k_ahb_rproc_info *rproc_info = ab_ahb->rproc_info; > char fw_name[ATH12K_USERPD_FW_NAME_LEN]; > char fw2_name[ATH12K_USERPD_FW_NAME_LEN]; > struct device *dev = ab->dev; > const struct firmware *fw, *fw2; > unsigned long time_left; > - phys_addr_t mem_phys; > - struct resource res; > - void *mem_region; > - size_t mem_size; > u32 pasid; > int ret; > > - ret = of_reserved_mem_region_to_resource_byname(dev->of_node, "q6-region", > - &res); > + ret = ath12k_ahb_get_fw_load_region(ab); > if (ret) > return ret; > > - mem_phys = res.start; > - mem_size = resource_size(&res); > - mem_region = devm_memremap(dev, mem_phys, mem_size, MEMREMAP_WC); > - if (IS_ERR(mem_region)) { > - ath12k_err(ab, "unable to map memory region: %pa+%zx\n", > - &res.start, mem_size); > - return PTR_ERR(mem_region); > - } > - > snprintf(fw_name, sizeof(fw_name), "%s/%s/%s%d%s", ATH12K_FW_DIR, > ab->hw_params->fw.dir, ATH12K_AHB_FW_PREFIX, ab_ahb->userpd_id, > ATH12K_AHB_FW_SUFFIX); > @@ -400,11 +425,13 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab) > > /* Load FW image to a reserved memory location */ > if (ab_ahb->scm_auth_enabled) > - ret = qcom_mdt_load(dev, fw, fw_name, pasid, mem_region, > - mem_phys, mem_size, &mem_phys); > + ret = qcom_mdt_load(dev, fw, fw_name, pasid, rproc_info->mem_region, > + rproc_info->mem_phys, rproc_info->mem_size, > + NULL); > else > - ret = qcom_mdt_load_no_init(dev, fw, fw_name, mem_region, > - mem_phys, mem_size, &mem_phys); > + ret = qcom_mdt_load_no_init(dev, fw, fw_name, rproc_info->mem_region, > + rproc_info->mem_phys, rproc_info->mem_size, > + NULL); > if (ret) { > ath12k_err(ab, "Failed to load MDT segments: %d\n", ret); > goto err_fw; > @@ -428,8 +455,9 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab) > goto err_fw2; > } > > - ret = qcom_mdt_load_no_init(dev, fw2, fw2_name, mem_region, mem_phys, > - mem_size, &mem_phys); > + ret = qcom_mdt_load_no_init(dev, fw2, fw2_name, rproc_info->mem_region, > + rproc_info->mem_phys, rproc_info->mem_size, > + NULL); > if (ret) { > ath12k_err(ab, "Failed to load MDT segments: %d\n", ret); > goto err_fw2; > @@ -877,6 +905,7 @@ static struct ath12k_ahb_rproc_info *ath12k_ahb_rproc_info_alloc(struct ath12k_b > rproc_info->rootpd_booted_by_driver = false; > rproc_info->userpd[ab_ahb->userpd_id - 1] = ab_ahb; > rproc_info->num_userpd = 1; > + rproc_info->shared_fw_loaded = false; > init_completion(&rproc_info->rootpd_ready); > ab_ahb->rproc_info = rproc_info; > > @@ -961,6 +990,76 @@ static int ath12k_ahb_boot_root_pd(struct ath12k_base *ab) > return 0; > } > > +static int ath12k_ahb_load_auth_shared_fw(struct ath12k_base *ab, > + struct ath12k_ahb_rproc_info *rproc_info, > + const char *fw_name, u32 pasid) > +{ > + int ret; > + nit: move this empty line below after the declaration part. > + const struct firmware *fw __free(firmware) = NULL; With that nit addressed Reviewed-by: Vasanthakumar Thiagarajan <[email protected]>