aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoic Pallardy <loic.pallardy@st.com>2018-07-27 09:14:43 -0400
committerBjorn Andersson <bjorn.andersson@linaro.org>2018-10-10 01:39:12 -0400
commitd7c51706d0956472b7c0530b1bf8fba32d82ee6b (patch)
tree1495450dd78e02d67ee084fa562dc2e9d37363a8
parentb0019ccd7e90178929ce1afe944ab85d8a39d7a4 (diff)
remoteproc: add alloc ops in rproc_mem_entry struct
Memory entry could be allocated in different ways (ioremap, dma_alloc_coherent, internal RAM allocator...). This patch introduces an alloc ops in rproc_mem_entry structure to associate dedicated allocation mechanism to each memory entry descriptor in order to do remote core agnostic from memory allocators. The introduction of this ops allows to perform allocation of all registered carveout at the same time, just before calling rproc_start(). It simplifies and makes uniform carveout management whatever origin. Signed-off-by: Loic Pallardy <loic.pallardy@st.com> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r--drivers/remoteproc/remoteproc_core.c261
-rw-r--r--include/linux/remoteproc.h7
2 files changed, 175 insertions, 93 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 800320d06cb8..9d17b3079506 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -642,74 +642,31 @@ out:
642} 642}
643 643
644/** 644/**
645 * rproc_release_carveout() - release acquired carveout 645 * rproc_alloc_carveout() - allocated specified carveout
646 * @rproc: rproc handle 646 * @rproc: rproc handle
647 * @mem: the memory entry to release 647 * @mem: the memory entry to allocate
648 *
649 * This function releases specified memory entry @mem allocated via
650 * dma_alloc_coherent() function by @rproc.
651 */
652static int rproc_release_carveout(struct rproc *rproc,
653 struct rproc_mem_entry *mem)
654{
655 struct device *dev = &rproc->dev;
656
657 /* clean up carveout allocations */
658 dma_free_coherent(dev->parent, mem->len, mem->va, mem->dma);
659 return 0;
660}
661
662/**
663 * rproc_handle_carveout() - handle phys contig memory allocation requests
664 * @rproc: rproc handle
665 * @rsc: the resource entry
666 * @avail: size of available data (for image validation)
667 *
668 * This function will handle firmware requests for allocation of physically
669 * contiguous memory regions.
670 *
671 * These request entries should come first in the firmware's resource table,
672 * as other firmware entries might request placing other data objects inside
673 * these memory regions (e.g. data/code segments, trace resource entries, ...).
674 * 648 *
675 * Allocating memory this way helps utilizing the reserved physical memory 649 * This function allocate specified memory entry @mem using
676 * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries 650 * dma_alloc_coherent() as default allocator
677 * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
678 * pressure is important; it may have a substantial impact on performance.
679 */ 651 */
680static int rproc_handle_carveout(struct rproc *rproc, 652static int rproc_alloc_carveout(struct rproc *rproc,
681 struct fw_rsc_carveout *rsc, 653 struct rproc_mem_entry *mem)
682 int offset, int avail)
683{ 654{
684 struct rproc_mem_entry *carveout, *mapping = NULL; 655 struct rproc_mem_entry *mapping = NULL;
685 struct device *dev = &rproc->dev; 656 struct device *dev = &rproc->dev;
686 dma_addr_t dma; 657 dma_addr_t dma;
687 void *va; 658 void *va;
688 int ret; 659 int ret;
689 660
690 if (sizeof(*rsc) > avail) { 661 va = dma_alloc_coherent(dev->parent, mem->len, &dma, GFP_KERNEL);
691 dev_err(dev, "carveout rsc is truncated\n");
692 return -EINVAL;
693 }
694
695 /* make sure reserved bytes are zeroes */
696 if (rsc->reserved) {
697 dev_err(dev, "carveout rsc has non zero reserved bytes\n");
698 return -EINVAL;
699 }
700
701 dev_dbg(dev, "carveout rsc: name: %s, da 0x%x, pa 0x%x, len 0x%x, flags 0x%x\n",
702 rsc->name, rsc->da, rsc->pa, rsc->len, rsc->flags);
703
704 va = dma_alloc_coherent(dev->parent, rsc->len, &dma, GFP_KERNEL);
705 if (!va) { 662 if (!va) {
706 dev_err(dev->parent, 663 dev_err(dev->parent,
707 "failed to allocate dma memory: len 0x%x\n", rsc->len); 664 "failed to allocate dma memory: len 0x%x\n", mem->len);
708 return -ENOMEM; 665 return -ENOMEM;
709 } 666 }
710 667
711 dev_dbg(dev, "carveout va %pK, dma %pad, len 0x%x\n", 668 dev_dbg(dev, "carveout va %pK, dma %pad, len 0x%x\n",
712 va, &dma, rsc->len); 669 va, &dma, mem->len);
713 670
714 /* 671 /*
715 * Ok, this is non-standard. 672 * Ok, this is non-standard.
@@ -729,22 +686,22 @@ static int rproc_handle_carveout(struct rproc *rproc,
729 * physical address in this case. 686 * physical address in this case.
730 */ 687 */
731 688
732 if (rsc->da != FW_RSC_ADDR_ANY && !rproc->domain) { 689 if (mem->da != FW_RSC_ADDR_ANY) {
733 dev_err(dev->parent, 690 if (!rproc->domain) {
734 "Bad carveout rsc configuration\n"); 691 dev_err(dev->parent,
735 ret = -ENOMEM; 692 "Bad carveout rsc configuration\n");
736 goto dma_free; 693 ret = -ENOMEM;
737 } 694 goto dma_free;
695 }
738 696
739 if (rsc->da != FW_RSC_ADDR_ANY && rproc->domain) {
740 mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); 697 mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
741 if (!mapping) { 698 if (!mapping) {
742 ret = -ENOMEM; 699 ret = -ENOMEM;
743 goto dma_free; 700 goto dma_free;
744 } 701 }
745 702
746 ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len, 703 ret = iommu_map(rproc->domain, mem->da, dma, mem->len,
747 rsc->flags); 704 mem->flags);
748 if (ret) { 705 if (ret) {
749 dev_err(dev, "iommu_map failed: %d\n", ret); 706 dev_err(dev, "iommu_map failed: %d\n", ret);
750 goto free_mapping; 707 goto free_mapping;
@@ -757,52 +714,102 @@ static int rproc_handle_carveout(struct rproc *rproc,
757 * We can't trust the remote processor not to change the 714 * We can't trust the remote processor not to change the
758 * resource table, so we must maintain this info independently. 715 * resource table, so we must maintain this info independently.
759 */ 716 */
760 mapping->da = rsc->da; 717 mapping->da = mem->da;
761 mapping->len = rsc->len; 718 mapping->len = mem->len;
762 list_add_tail(&mapping->node, &rproc->mappings); 719 list_add_tail(&mapping->node, &rproc->mappings);
763 720
764 dev_dbg(dev, "carveout mapped 0x%x to %pad\n", 721 dev_dbg(dev, "carveout mapped 0x%x to %pad\n",
765 rsc->da, &dma); 722 mem->da, &dma);
723 } else {
724 mem->da = (u32)dma;
766 } 725 }
767 726
768 /* 727 mem->dma = (u32)dma;
769 * Some remote processors might need to know the pa 728 mem->va = va;
770 * even though they are behind an IOMMU. E.g., OMAP4's
771 * remote M3 processor needs this so it can control
772 * on-chip hardware accelerators that are not behind
773 * the IOMMU, and therefor must know the pa.
774 *
775 * Generally we don't want to expose physical addresses
776 * if we don't have to (remote processors are generally
777 * _not_ trusted), so we might want to do this only for
778 * remote processor that _must_ have this (e.g. OMAP4's
779 * dual M3 subsystem).
780 *
781 * Non-IOMMU processors might also want to have this info.
782 * In this case, the device address and the physical address
783 * are the same.
784 */
785 rsc->pa = (u32)rproc_va_to_pa(va);
786
787 carveout = rproc_mem_entry_init(dev, va, dma, rsc->len, rsc->da,
788 rproc_release_carveout, rsc->name);
789 if (!carveout)
790 goto free_carv;
791
792 rproc_add_carveout(rproc, carveout);
793 729
794 return 0; 730 return 0;
795 731
796free_carv:
797 kfree(carveout);
798free_mapping: 732free_mapping:
799 kfree(mapping); 733 kfree(mapping);
800dma_free: 734dma_free:
801 dma_free_coherent(dev->parent, rsc->len, va, dma); 735 dma_free_coherent(dev->parent, mem->len, va, dma);
802 return ret; 736 return ret;
803} 737}
804 738
805/** 739/**
740 * rproc_release_carveout() - release acquired carveout
741 * @rproc: rproc handle
742 * @mem: the memory entry to release
743 *
744 * This function releases specified memory entry @mem allocated via
745 * rproc_alloc_carveout() function by @rproc.
746 */
747static int rproc_release_carveout(struct rproc *rproc,
748 struct rproc_mem_entry *mem)
749{
750 struct device *dev = &rproc->dev;
751
752 /* clean up carveout allocations */
753 dma_free_coherent(dev->parent, mem->len, mem->va, mem->dma);
754 return 0;
755}
756
757/**
758 * rproc_handle_carveout() - handle phys contig memory allocation requests
759 * @rproc: rproc handle
760 * @rsc: the resource entry
761 * @avail: size of available data (for image validation)
762 *
763 * This function will handle firmware requests for allocation of physically
764 * contiguous memory regions.
765 *
766 * These request entries should come first in the firmware's resource table,
767 * as other firmware entries might request placing other data objects inside
768 * these memory regions (e.g. data/code segments, trace resource entries, ...).
769 *
770 * Allocating memory this way helps utilizing the reserved physical memory
771 * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
772 * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
773 * pressure is important; it may have a substantial impact on performance.
774 */
775static int rproc_handle_carveout(struct rproc *rproc,
776 struct fw_rsc_carveout *rsc,
777 int offset, int avail)
778{
779 struct rproc_mem_entry *carveout;
780 struct device *dev = &rproc->dev;
781
782 if (sizeof(*rsc) > avail) {
783 dev_err(dev, "carveout rsc is truncated\n");
784 return -EINVAL;
785 }
786
787 /* make sure reserved bytes are zeroes */
788 if (rsc->reserved) {
789 dev_err(dev, "carveout rsc has non zero reserved bytes\n");
790 return -EINVAL;
791 }
792
793 dev_dbg(dev, "carveout rsc: name: %s, da 0x%x, pa 0x%x, len 0x%x, flags 0x%x\n",
794 rsc->name, rsc->da, rsc->pa, rsc->len, rsc->flags);
795
796 /* Register carveout in in list */
797 carveout = rproc_mem_entry_init(dev, 0, 0, rsc->len, rsc->da,
798 rproc_alloc_carveout,
799 rproc_release_carveout, rsc->name);
800 if (!carveout) {
801 dev_err(dev, "Can't allocate memory entry structure\n");
802 return -ENOMEM;
803 }
804
805 carveout->flags = rsc->flags;
806 carveout->rsc_offset = offset;
807 rproc_add_carveout(rproc, carveout);
808
809 return 0;
810}
811
812/**
806 * rproc_add_carveout() - register an allocated carveout region 813 * rproc_add_carveout() - register an allocated carveout region
807 * @rproc: rproc handle 814 * @rproc: rproc handle
808 * @mem: memory entry to register 815 * @mem: memory entry to register
@@ -832,6 +839,7 @@ EXPORT_SYMBOL(rproc_add_carveout);
832struct rproc_mem_entry * 839struct rproc_mem_entry *
833rproc_mem_entry_init(struct device *dev, 840rproc_mem_entry_init(struct device *dev,
834 void *va, dma_addr_t dma, int len, u32 da, 841 void *va, dma_addr_t dma, int len, u32 da,
842 int (*alloc)(struct rproc *, struct rproc_mem_entry *),
835 int (*release)(struct rproc *, struct rproc_mem_entry *), 843 int (*release)(struct rproc *, struct rproc_mem_entry *),
836 const char *name, ...) 844 const char *name, ...)
837{ 845{
@@ -846,7 +854,9 @@ rproc_mem_entry_init(struct device *dev,
846 mem->dma = dma; 854 mem->dma = dma;
847 mem->da = da; 855 mem->da = da;
848 mem->len = len; 856 mem->len = len;
857 mem->alloc = alloc;
849 mem->release = release; 858 mem->release = release;
859 mem->rsc_offset = FW_RSC_ADDR_ANY;
850 860
851 va_start(args, name); 861 va_start(args, name);
852 vsnprintf(mem->name, sizeof(mem->name), name, args); 862 vsnprintf(mem->name, sizeof(mem->name), name, args);
@@ -978,6 +988,63 @@ static void rproc_unprepare_subdevices(struct rproc *rproc)
978} 988}
979 989
980/** 990/**
991 * rproc_alloc_registered_carveouts() - allocate all carveouts registered
992 * in the list
993 * @rproc: the remote processor handle
994 *
995 * This function parses registered carveout list, performs allocation
996 * if alloc() ops registered and updates resource table information
997 * if rsc_offset set.
998 *
999 * Return: 0 on success
1000 */
1001static int rproc_alloc_registered_carveouts(struct rproc *rproc)
1002{
1003 struct rproc_mem_entry *entry, *tmp;
1004 struct fw_rsc_carveout *rsc;
1005 struct device *dev = &rproc->dev;
1006 int ret;
1007
1008 list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) {
1009 if (entry->alloc) {
1010 ret = entry->alloc(rproc, entry);
1011 if (ret) {
1012 dev_err(dev, "Unable to allocate carveout %s: %d\n",
1013 entry->name, ret);
1014 return -ENOMEM;
1015 }
1016 }
1017
1018 if (entry->rsc_offset != FW_RSC_ADDR_ANY) {
1019 /* update resource table */
1020 rsc = (void *)rproc->table_ptr + entry->rsc_offset;
1021
1022 /*
1023 * Some remote processors might need to know the pa
1024 * even though they are behind an IOMMU. E.g., OMAP4's
1025 * remote M3 processor needs this so it can control
1026 * on-chip hardware accelerators that are not behind
1027 * the IOMMU, and therefor must know the pa.
1028 *
1029 * Generally we don't want to expose physical addresses
1030 * if we don't have to (remote processors are generally
1031 * _not_ trusted), so we might want to do this only for
1032 * remote processor that _must_ have this (e.g. OMAP4's
1033 * dual M3 subsystem).
1034 *
1035 * Non-IOMMU processors might also want to have this info.
1036 * In this case, the device address and the physical address
1037 * are the same.
1038 */
1039 if (entry->va)
1040 rsc->pa = (u32)rproc_va_to_pa(entry->va);
1041 }
1042 }
1043
1044 return 0;
1045}
1046
1047/**
981 * rproc_coredump_cleanup() - clean up dump_segments list 1048 * rproc_coredump_cleanup() - clean up dump_segments list
982 * @rproc: the remote processor handle 1049 * @rproc: the remote processor handle
983 */ 1050 */
@@ -1149,6 +1216,14 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
1149 goto clean_up_resources; 1216 goto clean_up_resources;
1150 } 1217 }
1151 1218
1219 /* Allocate carveout resources associated to rproc */
1220 ret = rproc_alloc_registered_carveouts(rproc);
1221 if (ret) {
1222 dev_err(dev, "Failed to allocate associated carveouts: %d\n",
1223 ret);
1224 goto clean_up_resources;
1225 }
1226
1152 ret = rproc_start(rproc, fw); 1227 ret = rproc_start(rproc, fw);
1153 if (ret) 1228 if (ret)
1154 goto clean_up_resources; 1229 goto clean_up_resources;
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 8a350265d883..d251c091303c 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -317,6 +317,9 @@ struct rproc;
317 * @priv: associated data 317 * @priv: associated data
318 * @name: associated memory region name (optional) 318 * @name: associated memory region name (optional)
319 * @node: list node 319 * @node: list node
320 * @rsc_offset: offset in resource table
321 * @flags: iommu protection flags
322 * @alloc: specific memory allocator function
320 */ 323 */
321struct rproc_mem_entry { 324struct rproc_mem_entry {
322 void *va; 325 void *va;
@@ -326,6 +329,9 @@ struct rproc_mem_entry {
326 void *priv; 329 void *priv;
327 char name[32]; 330 char name[32];
328 struct list_head node; 331 struct list_head node;
332 u32 rsc_offset;
333 u32 flags;
334 int (*alloc)(struct rproc *rproc, struct rproc_mem_entry *mem);
329 int (*release)(struct rproc *rproc, struct rproc_mem_entry *mem); 335 int (*release)(struct rproc *rproc, struct rproc_mem_entry *mem);
330}; 336};
331 337
@@ -564,6 +570,7 @@ void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem);
564struct rproc_mem_entry * 570struct rproc_mem_entry *
565rproc_mem_entry_init(struct device *dev, 571rproc_mem_entry_init(struct device *dev,
566 void *va, dma_addr_t dma, int len, u32 da, 572 void *va, dma_addr_t dma, int len, u32 da,
573 int (*alloc)(struct rproc *, struct rproc_mem_entry *),
567 int (*release)(struct rproc *, struct rproc_mem_entry *), 574 int (*release)(struct rproc *, struct rproc_mem_entry *),
568 const char *name, ...); 575 const char *name, ...);
569 576