hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/remoteproc/qcom_q6v5_mss.c
....@@ -17,6 +17,7 @@
1717 #include <linux/module.h>
1818 #include <linux/of_address.h>
1919 #include <linux/of_device.h>
20
+#include <linux/of_reserved_mem.h>
2021 #include <linux/platform_device.h>
2122 #include <linux/pm_domain.h>
2223 #include <linux/pm_runtime.h>
....@@ -189,6 +190,9 @@
189190 void *mba_region;
190191 size_t mba_size;
191192 size_t dp_size;
193
+
194
+ phys_addr_t mdata_phys;
195
+ size_t mdata_size;
192196
193197 phys_addr_t mpss_phys;
194198 phys_addr_t mpss_reloc;
....@@ -816,14 +820,34 @@
816820 if (IS_ERR(metadata))
817821 return PTR_ERR(metadata);
818822
819
- ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs);
820
- if (!ptr) {
821
- kfree(metadata);
822
- dev_err(qproc->dev, "failed to allocate mdt buffer\n");
823
- return -ENOMEM;
823
+ if (qproc->mdata_phys) {
824
+ if (size > qproc->mdata_size) {
825
+ ret = -EINVAL;
826
+ dev_err(qproc->dev, "metadata size outside memory range\n");
827
+ goto free_metadata;
828
+ }
829
+
830
+ phys = qproc->mdata_phys;
831
+ ptr = memremap(qproc->mdata_phys, size, MEMREMAP_WC);
832
+ if (!ptr) {
833
+ ret = -EBUSY;
834
+ dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",
835
+ &qproc->mdata_phys, size);
836
+ goto free_metadata;
837
+ }
838
+ } else {
839
+ ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs);
840
+ if (!ptr) {
841
+ ret = -ENOMEM;
842
+ dev_err(qproc->dev, "failed to allocate mdt buffer\n");
843
+ goto free_metadata;
844
+ }
824845 }
825846
826847 memcpy(ptr, metadata, size);
848
+
849
+ if (qproc->mdata_phys)
850
+ memunmap(ptr);
827851
828852 /* Hypervisor mapping to access metadata by modem */
829853 mdata_perm = BIT(QCOM_SCM_VMID_HLOS);
....@@ -853,7 +877,9 @@
853877 "mdt buffer not reclaimed system may become unstable\n");
854878
855879 free_dma_attrs:
856
- dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs);
880
+ if (!qproc->mdata_phys)
881
+ dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs);
882
+free_metadata:
857883 kfree(metadata);
858884
859885 return ret < 0 ? ret : 0;
....@@ -1585,6 +1611,7 @@
15851611 static int q6v5_alloc_memory_region(struct q6v5 *qproc)
15861612 {
15871613 struct device_node *child;
1614
+ struct reserved_mem *rmem;
15881615 struct device_node *node;
15891616 struct resource r;
15901617 int ret;
....@@ -1637,6 +1664,26 @@
16371664 qproc->mpss_phys = qproc->mpss_reloc = r.start;
16381665 qproc->mpss_size = resource_size(&r);
16391666
1667
+ if (!child) {
1668
+ node = of_parse_phandle(qproc->dev->of_node, "memory-region", 2);
1669
+ } else {
1670
+ child = of_get_child_by_name(qproc->dev->of_node, "metadata");
1671
+ node = of_parse_phandle(child, "memory-region", 0);
1672
+ of_node_put(child);
1673
+ }
1674
+
1675
+ if (!node)
1676
+ return 0;
1677
+
1678
+ rmem = of_reserved_mem_lookup(node);
1679
+ if (!rmem) {
1680
+ dev_err(qproc->dev, "unable to resolve metadata region\n");
1681
+ return -EINVAL;
1682
+ }
1683
+
1684
+ qproc->mdata_phys = rmem->base;
1685
+ qproc->mdata_size = rmem->size;
1686
+
16401687 return 0;
16411688 }
16421689