Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ade9aae authored by Deepak Katragadda's avatar Deepak Katragadda
Browse files

soc: qcom: pil-msa: Allocate and load MBA and DP images at one location



Instead of allocating separate memory locations for the MBA
and Debug policy images, allocate memory once for both of
them. This is intended to save the Hypervisor from having
to program additional XPU slots.

CRs-Fixed: 882533
Change-Id: I8015148c29f528d56c9645d72d57bfe3776c379b
Signed-off-by: default avatarDeepak Katragadda <dkatraga@codeaurora.org>
parent 3e5d75b2
Loading
Loading
Loading
Loading
+76 −130
Original line number Diff line number Diff line
@@ -320,27 +320,18 @@ int __pil_mss_deinit_image(struct pil_desc *pil, bool err_path)
	if (q6_drv->ahb_clk_vote)
		clk_disable_unprepare(q6_drv->ahb_clk);

	/* In case of any failure where reclaim MBA memory
	/* In case of any failure where reclaiming MBA and DP memory
	 * could not happen, free the memory here */
	if (drv->q6->mba_virt) {
	if (drv->q6->mba_dp_virt) {
		if (pil->subsys_vmid > 0)
			pil_assign_mem_to_linux(pil, drv->q6->mba_phys,
						drv->q6->mba_size);
		dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_size,
				drv->q6->mba_virt, drv->q6->mba_phys,
			pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
						drv->q6->mba_dp_size);
		dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_dp_size,
				drv->q6->mba_dp_virt, drv->q6->mba_dp_phys,
				&drv->attrs_dma);
		drv->q6->mba_virt = NULL;
		drv->q6->mba_dp_virt = NULL;
	}

	if (drv->q6->dp_virt) {
		if (pil->subsys_vmid > 0)
			pil_assign_mem_to_linux(pil, drv->q6->dp_phys,
						drv->q6->dp_size);
		dma_free_attrs(&drv->mba_mem_dev, drv->q6->dp_size,
				drv->q6->dp_virt, drv->q6->dp_phys,
				&drv->attrs_dma);
		drv->q6->dp_virt = NULL;
	}
	return ret;
}

@@ -397,8 +388,8 @@ static int pil_mss_reset(struct pil_desc *pil)
	phys_addr_t start_addr = pil_get_entry_addr(pil);
	int ret;

	if (drv->mba_phys)
		start_addr = drv->mba_phys;
	if (drv->mba_dp_phys)
		start_addr = drv->mba_dp_phys;

	/*
	 * Bring subsystem out of reset and enable required
@@ -434,8 +425,8 @@ static int pil_mss_reset(struct pil_desc *pil)
	}

	/* Program DP Address */
	if (drv->dp_virt) {
		writel_relaxed(drv->dp_phys, drv->rmb_base +
	if (drv->dp_size) {
		writel_relaxed(start_addr + SZ_1M, drv->rmb_base +
			       RMB_PMI_CODE_START);
		writel_relaxed(drv->dp_size, drv->rmb_base +
			       RMB_PMI_CODE_LENGTH);
@@ -484,14 +475,12 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
	char fw_name[10] = "mba.mbn";
	char *dp_name = "msadp";
	char *fw_name_p;
	void *mba_virt;
	dma_addr_t mba_phys, mba_phys_end;
	void *mba_dp_virt;
	dma_addr_t mba_dp_phys, mba_dp_phys_end;
	int ret, count;
	const u8 *data;
	bool mba_mem_unprotect = false;

	fw_name_p = drv->non_elf_image ? fw_name_legacy : fw_name;
	/* Load and authenticate mba image */
	ret = request_firmware(&fw, fw_name_p, pil->dev);
	if (ret) {
		dev_err(pil->dev, "Failed to locate %s\n",
@@ -499,51 +488,22 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
		return ret;
	}

	drv->mba_size = SZ_1M;
	md->mba_mem_dev.coherent_dma_mask =
		DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
	init_dma_attrs(&md->attrs_dma);
	dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &md->attrs_dma);
	mba_virt = dma_alloc_attrs(&md->mba_mem_dev, drv->mba_size,
			&mba_phys, GFP_KERNEL, &md->attrs_dma);
	if (!mba_virt) {
		dev_err(pil->dev, "MBA metadata buffer allocation failed\n");
		ret = -ENOMEM;
		goto err_dma_alloc;
	}

	drv->mba_phys = mba_phys;
	drv->mba_virt = mba_virt;
	mba_phys_end = mba_phys + drv->mba_size;

	dev_info(pil->dev, "MBA: loading from %pa to %pa\n", &mba_phys,
								&mba_phys_end);
	/* Load the MBA image into memory */
	data = fw ? fw->data : NULL;
	if (!data) {
		dev_err(pil->dev, "MBA data is NULL\n");
		ret = -ENOMEM;
		goto err_mba_data;
		goto err_invalid_fw;
	}
	count = fw->size;
	memcpy(mba_virt, data, count);
	wmb();

	if (pil->subsys_vmid > 0) {
		ret = pil_assign_mem_to_subsys(pil, drv->mba_phys,
							drv->mba_size);
		if (ret) {
			pr_err("scm_call to unprotect MBA mem failed\n");
			goto err_mba_data;
		}
		mba_mem_unprotect = true;
	}
	drv->mba_dp_size = SZ_1M;
	md->mba_mem_dev.coherent_dma_mask =
		DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
	init_dma_attrs(&md->attrs_dma);
	dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &md->attrs_dma);

	/* Load modem debug policy */
	ret = request_firmware(&dp_fw, dp_name, pil->dev);
	if (ret) {
		drv->dp_virt = NULL;
		dev_warn(pil->dev, "MBA: Debug policy not present - %s\n",
		dev_warn(pil->dev, "Debug policy not present - %s. Continue.\n",
						dp_name);
	} else {
		if (!dp_fw || !dp_fw->data) {
@@ -551,31 +511,44 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
			ret = -ENOMEM;
			goto err_invalid_fw;
		}
		mba_virt = dma_alloc_attrs(&md->mba_mem_dev, dp_fw->size,
			&mba_phys, GFP_KERNEL, &md->attrs_dma);
		if (!mba_virt) {
			dev_err(pil->dev, "MBA: DP metadata buffer allocation failed\n");
		drv->dp_size = dp_fw->size;
		drv->mba_dp_size += drv->dp_size;
	}

	mba_dp_virt = dma_alloc_attrs(&md->mba_mem_dev, drv->mba_dp_size,
			&mba_dp_phys, GFP_KERNEL, &md->attrs_dma);
	if (!mba_dp_virt) {
		dev_err(pil->dev, "MBA metadata buffer allocation failed\n");
		ret = -ENOMEM;
		goto err_invalid_fw;
	}
		drv->dp_size = dp_fw->size;
		drv->dp_phys = mba_phys;
		drv->dp_virt = mba_virt;
		mba_phys_end = mba_phys + drv->dp_size;
		dev_info(pil->dev, "MBA: DP loading from %pa to %pa\n",
						 &mba_phys, &mba_phys_end);

		memcpy(mba_virt, dp_fw->data, dp_fw->size);
	drv->mba_dp_phys = mba_dp_phys;
	drv->mba_dp_virt = mba_dp_virt;
	mba_dp_phys_end = mba_dp_phys + drv->mba_dp_size;

	dev_info(pil->dev, "Loading MBA and DP (if present) from %pa to %pa\n",
					&mba_dp_phys, &mba_dp_phys_end);

	/* Load the MBA image into memory */
	count = fw->size;
	memcpy(mba_dp_virt, data, count);
	/* Ensure memcpy of the MBA memory is done before loading the DP */
	wmb();

	/* Load the DP image into memory */
	if (drv->mba_dp_size > SZ_1M) {
		memcpy(mba_dp_virt + SZ_1M, dp_fw->data, dp_fw->size);
		/* Ensure memcpy is done before powering up modem */
		wmb();
	}

	if (pil->subsys_vmid > 0) {
			ret = pil_assign_mem_to_subsys(pil, drv->dp_phys,
							drv->dp_size);
		ret = pil_assign_mem_to_subsys(pil, drv->mba_dp_phys,
							drv->mba_dp_size);
		if (ret) {
				pr_err("scm_call to unprotect DP mem failed\n");
				goto err_dp_scm;
			}
			pr_err("scm_call to unprotect MBA and DP mem failed\n");
			goto err_mba_data;
		}
	}

@@ -585,32 +558,24 @@ int pil_mss_reset_load_mba(struct pil_desc *pil)
		goto err_mss_reset;
	}

	if (drv->dp_virt)
	if (dp_fw)
		release_firmware(dp_fw);
	release_firmware(fw);

	return 0;

err_mss_reset:
	if (drv->dp_virt && pil->subsys_vmid > 0)
		pil_assign_mem_to_linux(pil, drv->dp_phys, drv->dp_size);
err_dp_scm:
	if (drv->dp_virt) {
		dma_free_attrs(&md->mba_mem_dev, dp_fw->size, drv->dp_virt,
				drv->dp_phys, &md->attrs_dma);
		drv->dp_virt = NULL;
	}
	if (pil->subsys_vmid > 0)
		pil_assign_mem_to_linux(pil, drv->mba_dp_phys,
							drv->mba_dp_size);
err_mba_data:
	dma_free_attrs(&md->mba_mem_dev, drv->mba_dp_size, drv->mba_dp_virt,
				drv->mba_dp_phys, &md->attrs_dma);
err_invalid_fw:
	if (dp_fw)
		release_firmware(dp_fw);
err_mba_data:
	if (mba_mem_unprotect && pil->subsys_vmid > 0)
		pil_assign_mem_to_linux(pil, drv->mba_phys, drv->mba_size);
	dma_free_attrs(&md->mba_mem_dev, drv->mba_size, drv->mba_virt,
				drv->mba_phys, &md->attrs_dma);
	drv->mba_virt = NULL;
err_dma_alloc:
	release_firmware(fw);
	drv->mba_dp_virt = NULL;
	return ret;
}

@@ -680,22 +645,13 @@ fail:
	if (drv->q6) {
		pil_mss_shutdown(pil);
		if (pil->subsys_vmid > 0)
			pil_assign_mem_to_linux(pil, drv->q6->mba_phys,
						drv->q6->mba_size);
		dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_size,
				drv->q6->mba_virt, drv->q6->mba_phys,
			pil_assign_mem_to_linux(pil, drv->q6->mba_dp_phys,
						drv->q6->mba_dp_size);
		dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_dp_size,
				drv->q6->mba_dp_virt, drv->q6->mba_dp_phys,
				&drv->attrs_dma);
		drv->q6->mba_virt = NULL;
		drv->q6->mba_dp_virt = NULL;

		if (drv->q6->dp_virt) {
			if (pil->subsys_vmid > 0)
				pil_assign_mem_to_linux(pil, drv->q6->dp_phys,
						drv->q6->dp_size);
			dma_free_attrs(&drv->mba_mem_dev, drv->q6->dp_size,
					drv->q6->dp_virt, drv->q6->dp_phys,
					&drv->attrs_dma);
			drv->q6->dp_virt = NULL;
		}
	}
	return ret;
}
@@ -757,27 +713,17 @@ static int pil_msa_mba_auth(struct pil_desc *pil)
	}

	if (drv->q6) {
		if (drv->q6->mba_virt) {
			/* Reclaim MBA memory. */
		if (drv->q6->mba_dp_virt) {
			/* Reclaim MBA and DP (if allocated) memory. */
			if (pil->subsys_vmid > 0)
				pil_assign_mem_to_linux(pil, drv->q6->mba_phys,
					drv->q6->mba_size);
			dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_size,
					drv->q6->mba_virt, drv->q6->mba_phys,
					&drv->attrs_dma);

			drv->q6->mba_virt = NULL;
		}

		if (drv->q6->dp_virt) {
			/* Reclaim Modem DP memory. */
			if (pil->subsys_vmid > 0)
				pil_assign_mem_to_linux(pil, drv->q6->dp_phys,
					drv->q6->dp_size);
			dma_free_attrs(&drv->mba_mem_dev, drv->q6->dp_size,
					drv->q6->dp_virt, drv->q6->dp_phys,
					&drv->attrs_dma);
			drv->q6->dp_virt = NULL;
				pil_assign_mem_to_linux(pil,
					drv->q6->mba_dp_phys,
					drv->q6->mba_dp_size);
			dma_free_attrs(&drv->mba_mem_dev, drv->q6->mba_dp_size,
					drv->q6->mba_dp_virt,
					drv->q6->mba_dp_phys, &drv->attrs_dma);

			drv->q6->mba_dp_virt = NULL;
		}
	}
	if (ret)
+3 −5
Original line number Diff line number Diff line
@@ -48,11 +48,9 @@ struct q6v5_data {
	bool is_booted;
	struct pil_desc desc;
	bool self_auth;
	phys_addr_t mba_phys;
	void *mba_virt;
	size_t mba_size;
	phys_addr_t dp_phys;
	void *dp_virt;
	phys_addr_t mba_dp_phys;
	void *mba_dp_virt;
	size_t mba_dp_size;
	size_t dp_size;
	bool qdsp6v55;
	bool qdsp6v5_2_0;