Commit f4e526ff authored by Bjorn Andersson's avatar Bjorn Andersson
Browse files

soc: qcom: mdt_loader: Extract PAS operations



Rather than passing a boolean to indicate if the PAS operations should
be performed from within __mdt_load(), extract them to their own helper
function.

This will allow clients to invoke this directly, with some
qcom_scm_pas_metadata context that they later needs to release, without
further having to complicate the prototype of qcom_mdt_load().

Signed-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20220128025513.97188-9-bjorn.andersson@linaro.org
parent ebeb20a9
Loading
Loading
Loading
Loading
+74 −36
Original line number Diff line number Diff line
@@ -188,28 +188,31 @@ void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
}
EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);

static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
			   const char *fw_name, int pas_id, void *mem_region,
			   phys_addr_t mem_phys, size_t mem_size,
			   phys_addr_t *reloc_base, bool pas_init)
/**
 * qcom_mdt_pas_init() - initialize PAS region for firmware loading
 * @dev:	device handle to associate resources with
 * @fw:		firmware object for the mdt file
 * @firmware:	name of the firmware, for construction of segment file names
 * @pas_id:	PAS identifier
 * @mem_phys:	physical address of allocated memory region
 * @ctx:	PAS metadata context, to be released by caller
 *
 * Returns 0 on success, negative errno otherwise.
 */
int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
		      const char *fw_name, int pas_id, phys_addr_t mem_phys,
		      struct qcom_scm_pas_metadata *ctx)
{
	const struct elf32_phdr *phdrs;
	const struct elf32_phdr *phdr;
	const struct elf32_hdr *ehdr;
	phys_addr_t mem_reloc;
	phys_addr_t min_addr = PHYS_ADDR_MAX;
	phys_addr_t max_addr = 0;
	size_t metadata_len;
	ssize_t offset;
	void *metadata;
	bool relocate = false;
	void *ptr;
	int ret = 0;
	int ret;
	int i;

	if (!fw || !mem_region || !mem_phys || !mem_size)
		return -EINVAL;

	ehdr = (struct elf32_hdr *)fw->data;
	phdrs = (struct elf32_phdr *)(ehdr + 1);

@@ -219,9 +222,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
		if (!mdt_phdr_valid(phdr))
			continue;

		if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
			relocate = true;

		if (phdr->p_paddr < min_addr)
			min_addr = phdr->p_paddr;

@@ -229,32 +229,66 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
			max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
	}

	if (pas_init) {
	metadata = qcom_mdt_read_metadata(fw, &metadata_len, fw_name, dev);
	if (IS_ERR(metadata)) {
		ret = PTR_ERR(metadata);
			dev_err(dev, "error %d reading firmware %s metadata\n",
				ret, fw_name);
		dev_err(dev, "error %d reading firmware %s metadata\n", ret, fw_name);
		goto out;
	}

		ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, NULL);

	ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, ctx);
	kfree(metadata);
	if (ret) {
		/* Invalid firmware metadata */
			dev_err(dev, "error %d initializing firmware %s\n",
				ret, fw_name);
		dev_err(dev, "error %d initializing firmware %s\n", ret, fw_name);
		goto out;
	}

	ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
	if (ret) {
		/* Unable to set up relocation */
			dev_err(dev, "error %d setting up firmware %s\n",
				ret, fw_name);
		dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
		goto out;
	}

out:
	return ret;
}
EXPORT_SYMBOL_GPL(qcom_mdt_pas_init);

static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
			   const char *fw_name, int pas_id, void *mem_region,
			   phys_addr_t mem_phys, size_t mem_size,
			   phys_addr_t *reloc_base, bool pas_init)
{
	const struct elf32_phdr *phdrs;
	const struct elf32_phdr *phdr;
	const struct elf32_hdr *ehdr;
	phys_addr_t mem_reloc;
	phys_addr_t min_addr = PHYS_ADDR_MAX;
	ssize_t offset;
	bool relocate = false;
	void *ptr;
	int ret = 0;
	int i;

	if (!fw || !mem_region || !mem_phys || !mem_size)
		return -EINVAL;

	ehdr = (struct elf32_hdr *)fw->data;
	phdrs = (struct elf32_phdr *)(ehdr + 1);

	for (i = 0; i < ehdr->e_phnum; i++) {
		phdr = &phdrs[i];

		if (!mdt_phdr_valid(phdr))
			continue;

		if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
			relocate = true;

		if (phdr->p_paddr < min_addr)
			min_addr = phdr->p_paddr;
	}

	if (relocate) {
@@ -319,8 +353,6 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
	if (reloc_base)
		*reloc_base = mem_reloc;

out:

	return ret;
}

@@ -342,6 +374,12 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw,
		  phys_addr_t mem_phys, size_t mem_size,
		  phys_addr_t *reloc_base)
{
	int ret;

	ret = qcom_mdt_pas_init(dev, fw, firmware, pas_id, mem_phys, NULL);
	if (ret)
		return ret;

	return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
			       mem_size, reloc_base, true);
}
+11 −0
Original line number Diff line number Diff line
@@ -10,10 +10,14 @@

struct device;
struct firmware;
struct qcom_scm_pas_metadata;

#if IS_ENABLED(CONFIG_QCOM_MDT_LOADER)

ssize_t qcom_mdt_get_size(const struct firmware *fw);
int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
		      const char *fw_name, int pas_id, phys_addr_t mem_phys,
		      struct qcom_scm_pas_metadata *pas_metadata_ctx);
int qcom_mdt_load(struct device *dev, const struct firmware *fw,
		  const char *fw_name, int pas_id, void *mem_region,
		  phys_addr_t mem_phys, size_t mem_size,
@@ -33,6 +37,13 @@ static inline ssize_t qcom_mdt_get_size(const struct firmware *fw)
	return -ENODEV;
}

static inline int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
				    const char *fw_name, int pas_id, phys_addr_t mem_phys,
				    struct qcom_scm_pas_metadata *pas_metadata_ctx)
{
	return -ENODEV;
}

static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw,
				const char *fw_name, int pas_id,
				void *mem_region, phys_addr_t mem_phys,