diff options
Diffstat (limited to 'drivers/remoteproc/remoteproc_elf_loader.c')
| -rw-r--r-- | drivers/remoteproc/remoteproc_elf_loader.c | 59 | 
1 files changed, 30 insertions, 29 deletions
| diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c index c523983a4aec..b17d72ec8603 100644 --- a/drivers/remoteproc/remoteproc_elf_loader.c +++ b/drivers/remoteproc/remoteproc_elf_loader.c @@ -39,8 +39,7 @@   *   * Make sure this fw image is sane.   */ -static int -rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw) +int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)  {  	const char *name = rproc->firmware;  	struct device *dev = &rproc->dev; @@ -98,6 +97,7 @@ rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)  	return 0;  } +EXPORT_SYMBOL(rproc_elf_sanity_check);  /**   * rproc_elf_get_boot_addr() - Get rproc's boot address. @@ -110,13 +110,13 @@ rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)   * Note that the boot address is not a configurable property of all remote   * processors. Some will always boot at a specific hard-coded address.   */ -static  u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)  {  	struct elf32_hdr *ehdr  = (struct elf32_hdr *)fw->data;  	return ehdr->e_entry;  } +EXPORT_SYMBOL(rproc_elf_get_boot_addr);  /**   * rproc_elf_load_segments() - load firmware segments to memory @@ -142,8 +142,7 @@ u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw)   * directly allocate memory for every segment/resource. This is not yet   * supported, though.   */ -static int -rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw) +int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)  {  	struct device *dev = &rproc->dev;  	struct elf32_hdr *ehdr; @@ -207,6 +206,7 @@ rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)  	return ret;  } +EXPORT_SYMBOL(rproc_elf_load_segments);  static struct elf32_shdr *  find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size) @@ -268,41 +268,49 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)  }  /** - * rproc_elf_find_rsc_table() - find the resource table + * rproc_elf_load_rsc_table() - load the resource table   * @rproc: the rproc handle   * @fw: the ELF firmware image - * @tablesz: place holder for providing back the table size   *   * This function finds the resource table inside the remote processor's - * firmware. It is used both upon the registration of @rproc (in order - * to look for and register the supported virito devices), and when the - * @rproc is booted. + * firmware, load it into the @cached_table and update @table_ptr.   * - * Returns the pointer to the resource table if it is found, and write its - * size into @tablesz. If a valid table isn't found, NULL is returned - * (and @tablesz isn't set). + * Return: 0 on success, negative errno on failure.   */ -static struct resource_table * -rproc_elf_find_rsc_table(struct rproc *rproc, const struct firmware *fw, -			 int *tablesz) +int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)  {  	struct elf32_hdr *ehdr;  	struct elf32_shdr *shdr;  	struct device *dev = &rproc->dev;  	struct resource_table *table = NULL;  	const u8 *elf_data = fw->data; +	size_t tablesz;  	ehdr = (struct elf32_hdr *)elf_data;  	shdr = find_table(dev, ehdr, fw->size);  	if (!shdr) -		return NULL; +		return -EINVAL;  	table = (struct resource_table *)(elf_data + shdr->sh_offset); -	*tablesz = shdr->sh_size; +	tablesz = shdr->sh_size; + +	/* +	 * Create a copy of the resource table. When a virtio device starts +	 * and calls vring_new_virtqueue() the address of the allocated vring +	 * will be stored in the cached_table. Before the device is started, +	 * cached_table will be copied into device memory. +	 */ +	rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL); +	if (!rproc->cached_table) +		return -ENOMEM; -	return table; +	rproc->table_ptr = rproc->cached_table; +	rproc->table_sz = tablesz; + +	return 0;  } +EXPORT_SYMBOL(rproc_elf_load_rsc_table);  /**   * rproc_elf_find_loaded_rsc_table() - find the loaded resource table @@ -315,8 +323,8 @@ rproc_elf_find_rsc_table(struct rproc *rproc, const struct firmware *fw,   * Returns the pointer to the resource table if it is found or NULL otherwise.   * If the table wasn't loaded yet the result is unspecified.   */ -static struct resource_table * -rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *fw) +struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, +						       const struct firmware *fw)  {  	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;  	struct elf32_shdr *shdr; @@ -327,11 +335,4 @@ rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware *fw)  	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);  } - -const struct rproc_fw_ops rproc_elf_fw_ops = { -	.load = rproc_elf_load_segments, -	.find_rsc_table = rproc_elf_find_rsc_table, -	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, -	.sanity_check = rproc_elf_sanity_check, -	.get_boot_addr = rproc_elf_get_boot_addr -}; +EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table); |