diff options
author | Bjorn Andersson <bjorn.andersson@linaro.org> | 2018-01-05 18:58:03 -0500 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2018-01-15 12:29:53 -0500 |
commit | 58b640906702bcc083ac783bf10325e22c67d9fc (patch) | |
tree | a9464c01c1f24b6977f7fefa67066a2e10eb4fea /drivers/remoteproc | |
parent | d4bb86f2c39cdd31338dd0274540596aa9ae82c3 (diff) |
remoteproc: Move resource table load logic to find
Extend the previous operation of finding the resource table in the ELF
with the extra step of populating the rproc struct with a copy and the
size. This allows drivers to override the mechanism used for acquiring
the resource table, or omit it for firmware that is known not to have a
resource table.
This leaves the custom, dummy, find_rsc_table implementations found in
some drivers dangling.
Reviewed-By: Loic Pallardy <loic.pallardy@st.com>
Tested-By: Loic Pallardy <loic.pallardy@st.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 32 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_elf_loader.c | 37 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_internal.h | 16 |
3 files changed, 35 insertions, 50 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 3160cfe897da..84e07d5b7c2c 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c | |||
@@ -907,8 +907,7 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | |||
907 | { | 907 | { |
908 | struct device *dev = &rproc->dev; | 908 | struct device *dev = &rproc->dev; |
909 | const char *name = rproc->firmware; | 909 | const char *name = rproc->firmware; |
910 | struct resource_table *table; | 910 | int ret; |
911 | int ret, tablesz; | ||
912 | 911 | ||
913 | ret = rproc_fw_sanity_check(rproc, fw); | 912 | ret = rproc_fw_sanity_check(rproc, fw); |
914 | if (ret) | 913 | if (ret) |
@@ -927,27 +926,11 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | |||
927 | } | 926 | } |
928 | 927 | ||
929 | rproc->bootaddr = rproc_get_boot_addr(rproc, fw); | 928 | rproc->bootaddr = rproc_get_boot_addr(rproc, fw); |
930 | ret = -EINVAL; | ||
931 | |||
932 | /* look for the resource table */ | ||
933 | table = rproc_find_rsc_table(rproc, fw, &tablesz); | ||
934 | if (!table) { | ||
935 | dev_err(dev, "Failed to find resource table\n"); | ||
936 | goto clean_up; | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * Create a copy of the resource table. When a virtio device starts | ||
941 | * and calls vring_new_virtqueue() the address of the allocated vring | ||
942 | * will be stored in the cached_table. Before the device is started, | ||
943 | * cached_table will be copied into device memory. | ||
944 | */ | ||
945 | rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL); | ||
946 | if (!rproc->cached_table) | ||
947 | goto clean_up; | ||
948 | 929 | ||
949 | rproc->table_ptr = rproc->cached_table; | 930 | /* load resource table */ |
950 | rproc->table_sz = tablesz; | 931 | ret = rproc_load_rsc_table(rproc, fw); |
932 | if (ret) | ||
933 | goto disable_iommu; | ||
951 | 934 | ||
952 | /* reset max_notifyid */ | 935 | /* reset max_notifyid */ |
953 | rproc->max_notifyid = -1; | 936 | rproc->max_notifyid = -1; |
@@ -967,11 +950,10 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | |||
967 | 950 | ||
968 | clean_up_resources: | 951 | clean_up_resources: |
969 | rproc_resource_cleanup(rproc); | 952 | rproc_resource_cleanup(rproc); |
970 | clean_up: | ||
971 | kfree(rproc->cached_table); | 953 | kfree(rproc->cached_table); |
972 | rproc->cached_table = NULL; | 954 | rproc->cached_table = NULL; |
973 | rproc->table_ptr = NULL; | 955 | rproc->table_ptr = NULL; |
974 | 956 | disable_iommu: | |
975 | rproc_disable_iommu(rproc); | 957 | rproc_disable_iommu(rproc); |
976 | return ret; | 958 | return ret; |
977 | } | 959 | } |
@@ -1443,7 +1425,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, | |||
1443 | /* Default to ELF loader if no load function is specified */ | 1425 | /* Default to ELF loader if no load function is specified */ |
1444 | if (!rproc->ops->load) { | 1426 | if (!rproc->ops->load) { |
1445 | rproc->ops->load = rproc_elf_load_segments; | 1427 | rproc->ops->load = rproc_elf_load_segments; |
1446 | rproc->ops->find_rsc_table = rproc_elf_find_rsc_table; | 1428 | rproc->ops->load_rsc_table = rproc_elf_load_rsc_table; |
1447 | rproc->ops->find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table; | 1429 | rproc->ops->find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table; |
1448 | rproc->ops->sanity_check = rproc_elf_sanity_check; | 1430 | rproc->ops->sanity_check = rproc_elf_sanity_check; |
1449 | rproc->ops->get_boot_addr = rproc_elf_get_boot_addr; | 1431 | rproc->ops->get_boot_addr = rproc_elf_get_boot_addr; |
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c index 822fa1bf893f..b17d72ec8603 100644 --- a/drivers/remoteproc/remoteproc_elf_loader.c +++ b/drivers/remoteproc/remoteproc_elf_loader.c | |||
@@ -268,42 +268,49 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size) | |||
268 | } | 268 | } |
269 | 269 | ||
270 | /** | 270 | /** |
271 | * rproc_elf_find_rsc_table() - find the resource table | 271 | * rproc_elf_load_rsc_table() - load the resource table |
272 | * @rproc: the rproc handle | 272 | * @rproc: the rproc handle |
273 | * @fw: the ELF firmware image | 273 | * @fw: the ELF firmware image |
274 | * @tablesz: place holder for providing back the table size | ||
275 | * | 274 | * |
276 | * This function finds the resource table inside the remote processor's | 275 | * This function finds the resource table inside the remote processor's |
277 | * firmware. It is used both upon the registration of @rproc (in order | 276 | * firmware, load it into the @cached_table and update @table_ptr. |
278 | * to look for and register the supported virito devices), and when the | ||
279 | * @rproc is booted. | ||
280 | * | 277 | * |
281 | * Returns the pointer to the resource table if it is found, and write its | 278 | * Return: 0 on success, negative errno on failure. |
282 | * size into @tablesz. If a valid table isn't found, NULL is returned | ||
283 | * (and @tablesz isn't set). | ||
284 | */ | 279 | */ |
285 | struct resource_table *rproc_elf_find_rsc_table(struct rproc *rproc, | 280 | int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw) |
286 | const struct firmware *fw, | ||
287 | int *tablesz) | ||
288 | { | 281 | { |
289 | struct elf32_hdr *ehdr; | 282 | struct elf32_hdr *ehdr; |
290 | struct elf32_shdr *shdr; | 283 | struct elf32_shdr *shdr; |
291 | struct device *dev = &rproc->dev; | 284 | struct device *dev = &rproc->dev; |
292 | struct resource_table *table = NULL; | 285 | struct resource_table *table = NULL; |
293 | const u8 *elf_data = fw->data; | 286 | const u8 *elf_data = fw->data; |
287 | size_t tablesz; | ||
294 | 288 | ||
295 | ehdr = (struct elf32_hdr *)elf_data; | 289 | ehdr = (struct elf32_hdr *)elf_data; |
296 | 290 | ||
297 | shdr = find_table(dev, ehdr, fw->size); | 291 | shdr = find_table(dev, ehdr, fw->size); |
298 | if (!shdr) | 292 | if (!shdr) |
299 | return NULL; | 293 | return -EINVAL; |
300 | 294 | ||
301 | table = (struct resource_table *)(elf_data + shdr->sh_offset); | 295 | table = (struct resource_table *)(elf_data + shdr->sh_offset); |
302 | *tablesz = shdr->sh_size; | 296 | tablesz = shdr->sh_size; |
297 | |||
298 | /* | ||
299 | * Create a copy of the resource table. When a virtio device starts | ||
300 | * and calls vring_new_virtqueue() the address of the allocated vring | ||
301 | * will be stored in the cached_table. Before the device is started, | ||
302 | * cached_table will be copied into device memory. | ||
303 | */ | ||
304 | rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL); | ||
305 | if (!rproc->cached_table) | ||
306 | return -ENOMEM; | ||
303 | 307 | ||
304 | return table; | 308 | rproc->table_ptr = rproc->cached_table; |
309 | rproc->table_sz = tablesz; | ||
310 | |||
311 | return 0; | ||
305 | } | 312 | } |
306 | EXPORT_SYMBOL(rproc_elf_find_rsc_table); | 313 | EXPORT_SYMBOL(rproc_elf_load_rsc_table); |
307 | 314 | ||
308 | /** | 315 | /** |
309 | * rproc_elf_find_loaded_rsc_table() - find the loaded resource table | 316 | * rproc_elf_find_loaded_rsc_table() - find the loaded resource table |
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index a42690c514e2..55a2950c5cb7 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h | |||
@@ -57,9 +57,7 @@ int rproc_trigger_recovery(struct rproc *rproc); | |||
57 | int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw); | 57 | int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw); |
58 | u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw); | 58 | u32 rproc_elf_get_boot_addr(struct rproc *rproc, const struct firmware *fw); |
59 | int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw); | 59 | int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw); |
60 | struct resource_table *rproc_elf_find_rsc_table(struct rproc *rproc, | 60 | int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw); |
61 | const struct firmware *fw, | ||
62 | int *tablesz); | ||
63 | struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, | 61 | struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc, |
64 | const struct firmware *fw); | 62 | const struct firmware *fw); |
65 | 63 | ||
@@ -90,15 +88,13 @@ int rproc_load_segments(struct rproc *rproc, const struct firmware *fw) | |||
90 | return -EINVAL; | 88 | return -EINVAL; |
91 | } | 89 | } |
92 | 90 | ||
93 | static inline | 91 | static inline int rproc_load_rsc_table(struct rproc *rproc, |
94 | struct resource_table *rproc_find_rsc_table(struct rproc *rproc, | 92 | const struct firmware *fw) |
95 | const struct firmware *fw, | ||
96 | int *tablesz) | ||
97 | { | 93 | { |
98 | if (rproc->ops->find_rsc_table) | 94 | if (rproc->ops->load_rsc_table) |
99 | return rproc->ops->find_rsc_table(rproc, fw, tablesz); | 95 | return rproc->ops->load_rsc_table(rproc, fw); |
100 | 96 | ||
101 | return NULL; | 97 | return 0; |
102 | } | 98 | } |
103 | 99 | ||
104 | static inline | 100 | static inline |