aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorOhad Ben-Cohen <ohad@wizery.com>2013-04-07 07:06:07 -0400
committerOhad Ben-Cohen <ohad@wizery.com>2013-04-07 07:06:07 -0400
commita2b950ac7b1e6442919ee9e79c4963e134698869 (patch)
tree7ecec79d66796b06db5c9d79144d17e1bc496bad /drivers/remoteproc
parentba7290e01663787fcfc2bedaff6232359d4ff248 (diff)
remoteproc: perserve resource table data
Copy resource table from first to second firmware loading. After firmware is loaded to memory, update the vdevs resource pointer to the resource table kept in device memory. Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com> Acked-by: Ido Yariv <ido@wizery.com> [rebase, terminology and style changes] Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/Kconfig1
-rw-r--r--drivers/remoteproc/remoteproc_core.c98
2 files changed, 79 insertions, 20 deletions
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index cc1f7bf53fd0..289e867a77dd 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -4,6 +4,7 @@ menu "Remoteproc drivers"
4config REMOTEPROC 4config REMOTEPROC
5 tristate 5 tristate
6 depends on HAS_DMA 6 depends on HAS_DMA
7 select CRC32
7 select FW_CONFIG 8 select FW_CONFIG
8 select VIRTIO 9 select VIRTIO
9 10
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 9d2a4ac6c706..617b825aa553 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -37,6 +37,7 @@
37#include <linux/iommu.h> 37#include <linux/iommu.h>
38#include <linux/idr.h> 38#include <linux/idr.h>
39#include <linux/elf.h> 39#include <linux/elf.h>
40#include <linux/crc32.h>
40#include <linux/virtio_ids.h> 41#include <linux/virtio_ids.h>
41#include <linux/virtio_ring.h> 42#include <linux/virtio_ring.h>
42#include <asm/byteorder.h> 43#include <asm/byteorder.h>
@@ -45,7 +46,8 @@
45 46
46typedef int (*rproc_handle_resources_t)(struct rproc *rproc, 47typedef int (*rproc_handle_resources_t)(struct rproc *rproc,
47 struct resource_table *table, int len); 48 struct resource_table *table, int len);
48typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); 49typedef int (*rproc_handle_resource_t)(struct rproc *rproc,
50 void *, int offset, int avail);
49 51
50/* Unique indices for remoteproc devices */ 52/* Unique indices for remoteproc devices */
51static DEFINE_IDA(rproc_dev_index); 53static DEFINE_IDA(rproc_dev_index);
@@ -302,7 +304,7 @@ void rproc_free_vring(struct rproc_vring *rvring)
302 * Returns 0 on success, or an appropriate error code otherwise 304 * Returns 0 on success, or an appropriate error code otherwise
303 */ 305 */
304static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, 306static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
305 int avail) 307 int offset, int avail)
306{ 308{
307 struct device *dev = &rproc->dev; 309 struct device *dev = &rproc->dev;
308 struct rproc_vdev *rvdev; 310 struct rproc_vdev *rvdev;
@@ -346,6 +348,9 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
346 /* remember the device features */ 348 /* remember the device features */
347 rvdev->dfeatures = rsc->dfeatures; 349 rvdev->dfeatures = rsc->dfeatures;
348 350
351 /* remember the resource offset*/
352 rvdev->rsc_offset = offset;
353
349 list_add_tail(&rvdev->node, &rproc->rvdevs); 354 list_add_tail(&rvdev->node, &rproc->rvdevs);
350 355
351 /* it is now safe to add the virtio device */ 356 /* it is now safe to add the virtio device */
@@ -377,7 +382,7 @@ free_rvdev:
377 * Returns 0 on success, or an appropriate error code otherwise 382 * Returns 0 on success, or an appropriate error code otherwise
378 */ 383 */
379static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, 384static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
380 int avail) 385 int offset, int avail)
381{ 386{
382 struct rproc_mem_entry *trace; 387 struct rproc_mem_entry *trace;
383 struct device *dev = &rproc->dev; 388 struct device *dev = &rproc->dev;
@@ -459,7 +464,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
459 * are outside those ranges. 464 * are outside those ranges.
460 */ 465 */
461static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, 466static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc,
462 int avail) 467 int offset, int avail)
463{ 468{
464 struct rproc_mem_entry *mapping; 469 struct rproc_mem_entry *mapping;
465 struct device *dev = &rproc->dev; 470 struct device *dev = &rproc->dev;
@@ -532,7 +537,9 @@ out:
532 * pressure is important; it may have a substantial impact on performance. 537 * pressure is important; it may have a substantial impact on performance.
533 */ 538 */
534static int rproc_handle_carveout(struct rproc *rproc, 539static int rproc_handle_carveout(struct rproc *rproc,
535 struct fw_rsc_carveout *rsc, int avail) 540 struct fw_rsc_carveout *rsc,
541 int offset, int avail)
542
536{ 543{
537 struct rproc_mem_entry *carveout, *mapping; 544 struct rproc_mem_entry *carveout, *mapping;
538 struct device *dev = &rproc->dev; 545 struct device *dev = &rproc->dev;
@@ -655,7 +662,7 @@ free_carv:
655} 662}
656 663
657static int rproc_count_vrings(struct rproc *rproc, struct fw_rsc_vdev *rsc, 664static int rproc_count_vrings(struct rproc *rproc, struct fw_rsc_vdev *rsc,
658 int avail) 665 int offset, int avail)
659{ 666{
660 /* Summarize the number of notification IDs */ 667 /* Summarize the number of notification IDs */
661 rproc->max_notifyid += rsc->num_of_vrings; 668 rproc->max_notifyid += rsc->num_of_vrings;
@@ -683,17 +690,16 @@ static rproc_handle_resource_t rproc_count_vrings_handler[RSC_LAST] = {
683}; 690};
684 691
685/* handle firmware resource entries before booting the remote processor */ 692/* handle firmware resource entries before booting the remote processor */
686static int rproc_handle_resources(struct rproc *rproc, 693static int rproc_handle_resources(struct rproc *rproc, int len,
687 struct resource_table *table, int len,
688 rproc_handle_resource_t handlers[RSC_LAST]) 694 rproc_handle_resource_t handlers[RSC_LAST])
689{ 695{
690 struct device *dev = &rproc->dev; 696 struct device *dev = &rproc->dev;
691 rproc_handle_resource_t handler; 697 rproc_handle_resource_t handler;
692 int ret = 0, i; 698 int ret = 0, i;
693 699
694 for (i = 0; i < table->num; i++) { 700 for (i = 0; i < rproc->table_ptr->num; i++) {
695 int offset = table->offset[i]; 701 int offset = rproc->table_ptr->offset[i];
696 struct fw_rsc_hdr *hdr = (void *)table + offset; 702 struct fw_rsc_hdr *hdr = (void *)rproc->table_ptr + offset;
697 int avail = len - offset - sizeof(*hdr); 703 int avail = len - offset - sizeof(*hdr);
698 void *rsc = (void *)hdr + sizeof(*hdr); 704 void *rsc = (void *)hdr + sizeof(*hdr);
699 705
@@ -714,7 +720,7 @@ static int rproc_handle_resources(struct rproc *rproc,
714 if (!handler) 720 if (!handler)
715 continue; 721 continue;
716 722
717 ret = handler(rproc, rsc, avail); 723 ret = handler(rproc, rsc, offset + sizeof(*hdr), avail);
718 if (ret) 724 if (ret)
719 break; 725 break;
720 } 726 }
@@ -772,9 +778,12 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
772{ 778{
773 struct device *dev = &rproc->dev; 779 struct device *dev = &rproc->dev;
774 const char *name = rproc->firmware; 780 const char *name = rproc->firmware;
775 struct resource_table *table; 781 struct resource_table *table, *loaded_table;
776 int ret, tablesz; 782 int ret, tablesz;
777 783
784 if (!rproc->table_ptr)
785 return -ENOMEM;
786
778 ret = rproc_fw_sanity_check(rproc, fw); 787 ret = rproc_fw_sanity_check(rproc, fw);
779 if (ret) 788 if (ret)
780 return ret; 789 return ret;
@@ -800,9 +809,15 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
800 goto clean_up; 809 goto clean_up;
801 } 810 }
802 811
812 /* Verify that resource table in loaded fw is unchanged */
813 if (rproc->table_csum != crc32(0, table, tablesz)) {
814 dev_err(dev, "resource checksum failed, fw changed?\n");
815 ret = -EINVAL;
816 goto clean_up;
817 }
818
803 /* handle fw resources which are required to boot rproc */ 819 /* handle fw resources which are required to boot rproc */
804 ret = rproc_handle_resources(rproc, table, tablesz, 820 ret = rproc_handle_resources(rproc, tablesz, rproc_loading_handlers);
805 rproc_loading_handlers);
806 if (ret) { 821 if (ret) {
807 dev_err(dev, "Failed to process resources: %d\n", ret); 822 dev_err(dev, "Failed to process resources: %d\n", ret);
808 goto clean_up; 823 goto clean_up;
@@ -815,6 +830,19 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
815 goto clean_up; 830 goto clean_up;
816 } 831 }
817 832
833 /*
834 * The starting device has been given the rproc->cached_table as the
835 * resource table. The address of the vring along with the other
836 * allocated resources (carveouts etc) is stored in cached_table.
837 * In order to pass this information to the remote device we must
838 * copy this information to device memory.
839 */
840 loaded_table = rproc_find_loaded_rsc_table(rproc, fw);
841 if (!loaded_table)
842 goto clean_up;
843
844 memcpy(loaded_table, rproc->cached_table, tablesz);
845
818 /* power up the remote processor */ 846 /* power up the remote processor */
819 ret = rproc->ops->start(rproc); 847 ret = rproc->ops->start(rproc);
820 if (ret) { 848 if (ret) {
@@ -822,6 +850,13 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
822 goto clean_up; 850 goto clean_up;
823 } 851 }
824 852
853 /*
854 * Update table_ptr so that all subsequent vring allocations and
855 * virtio fields manipulation update the actual loaded resource table
856 * in device memory.
857 */
858 rproc->table_ptr = loaded_table;
859
825 rproc->state = RPROC_RUNNING; 860 rproc->state = RPROC_RUNNING;
826 861
827 dev_info(dev, "remote processor %s is now up\n", rproc->name); 862 dev_info(dev, "remote processor %s is now up\n", rproc->name);
@@ -856,16 +891,30 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
856 if (!table) 891 if (!table)
857 goto out; 892 goto out;
858 893
894 rproc->table_csum = crc32(0, table, tablesz);
895
896 /*
897 * Create a copy of the resource table. When a virtio device starts
898 * and calls vring_new_virtqueue() the address of the allocated vring
899 * will be stored in the cached_table. Before the device is started,
900 * cached_table will be copied into devic memory.
901 */
902 rproc->cached_table = kmalloc(tablesz, GFP_KERNEL);
903 if (!rproc->cached_table)
904 goto out;
905
906 memcpy(rproc->cached_table, table, tablesz);
907 rproc->table_ptr = rproc->cached_table;
908
859 /* count the number of notify-ids */ 909 /* count the number of notify-ids */
860 rproc->max_notifyid = -1; 910 rproc->max_notifyid = -1;
861 ret = rproc_handle_resources(rproc, table, tablesz, 911 ret = rproc_handle_resources(rproc, tablesz, rproc_count_vrings_handler);
862 rproc_count_vrings_handler);
863
864 /* look for virtio devices and register them */
865 ret = rproc_handle_resources(rproc, table, tablesz, rproc_vdev_handler);
866 if (ret) 912 if (ret)
867 goto out; 913 goto out;
868 914
915 /* look for virtio devices and register them */
916 ret = rproc_handle_resources(rproc, tablesz, rproc_vdev_handler);
917
869out: 918out:
870 release_firmware(fw); 919 release_firmware(fw);
871 /* allow rproc_del() contexts, if any, to proceed */ 920 /* allow rproc_del() contexts, if any, to proceed */
@@ -923,6 +972,9 @@ int rproc_trigger_recovery(struct rproc *rproc)
923 /* wait until there is no more rproc users */ 972 /* wait until there is no more rproc users */
924 wait_for_completion(&rproc->crash_comp); 973 wait_for_completion(&rproc->crash_comp);
925 974
975 /* Free the copy of the resource table */
976 kfree(rproc->cached_table);
977
926 return rproc_add_virtio_devices(rproc); 978 return rproc_add_virtio_devices(rproc);
927} 979}
928 980
@@ -1078,6 +1130,9 @@ void rproc_shutdown(struct rproc *rproc)
1078 1130
1079 rproc_disable_iommu(rproc); 1131 rproc_disable_iommu(rproc);
1080 1132
1133 /* Give the next start a clean resource table */
1134 rproc->table_ptr = rproc->cached_table;
1135
1081 /* if in crash state, unlock crash handler */ 1136 /* if in crash state, unlock crash handler */
1082 if (rproc->state == RPROC_CRASHED) 1137 if (rproc->state == RPROC_CRASHED)
1083 complete_all(&rproc->crash_comp); 1138 complete_all(&rproc->crash_comp);
@@ -1288,6 +1343,9 @@ int rproc_del(struct rproc *rproc)
1288 list_for_each_entry_safe(rvdev, tmp, &rproc->rvdevs, node) 1343 list_for_each_entry_safe(rvdev, tmp, &rproc->rvdevs, node)
1289 rproc_remove_virtio_dev(rvdev); 1344 rproc_remove_virtio_dev(rvdev);
1290 1345
1346 /* Free the copy of the resource table */
1347 kfree(rproc->cached_table);
1348
1291 device_del(&rproc->dev); 1349 device_del(&rproc->dev);
1292 1350
1293 return 0; 1351 return 0;