Browse Source

msm: camera: memmgr: Add dma-buf-heaps usage in camera

Use dma-buf-heaps for allocating buffers. Keep ion usage
to support kernels without dma-buf-heaps support.

CRs-Fixed: 2852327
Change-Id: I3ebcb591827d9b8e5366f716efd08e4cd6f1070a
Signed-off-by: Pavan Kumar Chilamkurthi <[email protected]>
Pavan Kumar Chilamkurthi 4 years ago
parent
commit
68eda98831

+ 220 - 6
drivers/cam_req_mgr/cam_mem_mgr.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -22,6 +22,11 @@
 static struct cam_mem_table tbl;
 static struct cam_mem_table tbl;
 static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED);
 static atomic_t cam_mem_mgr_state = ATOMIC_INIT(CAM_MEM_MGR_UNINITIALIZED);
 
 
+#if IS_REACHABLE(CONFIG_DMABUF_HEAPS)
+static void cam_mem_mgr_put_dma_heaps(void);
+static int cam_mem_mgr_get_dma_heaps(void);
+#endif
+
 static void cam_mem_mgr_print_tbl(void)
 static void cam_mem_mgr_print_tbl(void)
 {
 {
 	int i;
 	int i;
@@ -163,6 +168,7 @@ int cam_mem_mgr_init(void)
 {
 {
 	int i;
 	int i;
 	int bitmap_size;
 	int bitmap_size;
+	int rc = 0;
 
 
 	memset(tbl.bufq, 0, sizeof(tbl.bufq));
 	memset(tbl.bufq, 0, sizeof(tbl.bufq));
 
 
@@ -171,10 +177,19 @@ int cam_mem_mgr_init(void)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
+#if IS_REACHABLE(CONFIG_DMABUF_HEAPS)
+	rc = cam_mem_mgr_get_dma_heaps();
+	if (rc) {
+		CAM_ERR(CAM_MEM, "Failed in getting dma heaps rc=%d", rc);
+		return rc;
+	}
+#endif
 	bitmap_size = BITS_TO_LONGS(CAM_MEM_BUFQ_MAX) * sizeof(long);
 	bitmap_size = BITS_TO_LONGS(CAM_MEM_BUFQ_MAX) * sizeof(long);
 	tbl.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
 	tbl.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!tbl.bitmap)
-		return -ENOMEM;
+	if (!tbl.bitmap) {
+		rc = -ENOMEM;
+		goto put_heaps;
+	}
 
 
 	tbl.bits = bitmap_size * BITS_PER_BYTE;
 	tbl.bits = bitmap_size * BITS_PER_BYTE;
 	bitmap_zero(tbl.bitmap, tbl.bits);
 	bitmap_zero(tbl.bitmap, tbl.bits);
@@ -192,6 +207,11 @@ int cam_mem_mgr_init(void)
 	cam_mem_mgr_create_debug_fs();
 	cam_mem_mgr_create_debug_fs();
 
 
 	return 0;
 	return 0;
+put_heaps:
+#if IS_REACHABLE(CONFIG_DMABUF_HEAPS)
+	cam_mem_mgr_put_dma_heaps();
+#endif
+	return rc;
 }
 }
 
 
 static int32_t cam_mem_get_slot(void)
 static int32_t cam_mem_get_slot(void)
@@ -365,6 +385,10 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
 		goto end;
 		goto end;
 	}
 	}
 
 
+#if IS_REACHABLE(CONFIG_DMABUF_HEAPS)
+	CAM_DBG(CAM_MEM, "Calling dmap buf APIs for cache operations");
+	cache_dir = DMA_BIDIRECTIONAL;
+#else
 	if (dmabuf_flag & ION_FLAG_CACHED) {
 	if (dmabuf_flag & ION_FLAG_CACHED) {
 		switch (cmd->mem_cache_ops) {
 		switch (cmd->mem_cache_ops) {
 		case CAM_MEM_CLEAN_CACHE:
 		case CAM_MEM_CLEAN_CACHE:
@@ -386,7 +410,7 @@ int cam_mem_mgr_cache_ops(struct cam_mem_cache_ops_cmd *cmd)
 		CAM_DBG(CAM_MEM, "BUF is not cached");
 		CAM_DBG(CAM_MEM, "BUF is not cached");
 		goto end;
 		goto end;
 	}
 	}
-
+#endif
 	rc = dma_buf_begin_cpu_access(tbl.bufq[idx].dma_buf,
 	rc = dma_buf_begin_cpu_access(tbl.bufq[idx].dma_buf,
 		(cmd->mem_cache_ops == CAM_MEM_CLEAN_INV_CACHE) ?
 		(cmd->mem_cache_ops == CAM_MEM_CLEAN_INV_CACHE) ?
 		DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
 		DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
@@ -408,6 +432,192 @@ end:
 }
 }
 EXPORT_SYMBOL(cam_mem_mgr_cache_ops);
 EXPORT_SYMBOL(cam_mem_mgr_cache_ops);
 
 
+#if IS_REACHABLE(CONFIG_DMABUF_HEAPS)
+static void cam_mem_mgr_put_dma_heaps(void)
+{
+	CAM_DBG(CAM_MEM, "Releasing DMA Buf heaps usage");
+}
+
+static int cam_mem_mgr_get_dma_heaps(void)
+{
+	int rc = 0;
+
+	tbl.system_heap = NULL;
+	tbl.system_uncached_heap = NULL;
+	tbl.camera_heap = NULL;
+	tbl.camera_uncached_heap = NULL;
+	tbl.secure_display_heap = NULL;
+
+	tbl.system_heap = dma_heap_find("qcom,system");
+	if (IS_ERR_OR_NULL(tbl.system_heap)) {
+		rc = PTR_ERR(tbl.system_heap);
+		CAM_ERR(CAM_MEM, "qcom system heap not found, rc=%d", rc);
+		tbl.system_heap = NULL;
+		goto put_heaps;
+	}
+
+	tbl.system_uncached_heap = dma_heap_find("qcom,system-uncached");
+	if (IS_ERR_OR_NULL(tbl.system_uncached_heap)) {
+		if (tbl.force_cache_allocs) {
+			/* optional, we anyway do not use uncached */
+			CAM_DBG(CAM_MEM,
+				"qcom system-uncached heap not found, err=%d",
+				PTR_ERR(tbl.system_uncached_heap));
+			tbl.system_uncached_heap = NULL;
+		} else {
+			/* fatal, must need uncached heaps */
+			rc = PTR_ERR(tbl.system_uncached_heap);
+			CAM_ERR(CAM_MEM,
+				"qcom system-uncached heap not found, rc=%d",
+				rc);
+			tbl.system_uncached_heap = NULL;
+			goto put_heaps;
+		}
+	}
+
+	tbl.secure_display_heap = dma_heap_find("qcom,secure-display");
+	if (IS_ERR_OR_NULL(tbl.secure_display_heap)) {
+		rc = PTR_ERR(tbl.secure_display_heap);
+		CAM_ERR(CAM_MEM, "qcom,secure-display heap not found, rc=%d",
+			rc);
+		tbl.secure_display_heap = NULL;
+		goto put_heaps;
+	}
+
+	tbl.camera_heap = dma_heap_find("qcom,camera");
+	if (IS_ERR_OR_NULL(tbl.camera_heap)) {
+		/* optional heap, not a fatal error */
+		CAM_DBG(CAM_MEM, "qcom camera heap not found, err=%d",
+			PTR_ERR(tbl.camera_heap));
+		tbl.camera_heap = NULL;
+	}
+
+	tbl.camera_uncached_heap = dma_heap_find("qcom,camera-uncached");
+	if (IS_ERR_OR_NULL(tbl.camera_uncached_heap)) {
+		/* optional heap, not a fatal error */
+		CAM_DBG(CAM_MEM, "qcom camera heap not found, err=%d",
+			PTR_ERR(tbl.camera_uncached_heap));
+		tbl.camera_uncached_heap = NULL;
+	}
+
+	CAM_INFO(CAM_MEM,
+		"Heaps : system=%pK, system_uncached=%pK, camera=%pK, camera-uncached=%pK, secure_display=%pK",
+		tbl.system_heap, tbl.system_uncached_heap,
+		tbl.camera_heap, tbl.camera_uncached_heap,
+		tbl.secure_display_heap);
+
+	return 0;
+put_heaps:
+	cam_mem_mgr_put_dma_heaps();
+	return rc;
+}
+
+static int cam_mem_util_get_dma_buf(size_t len,
+	unsigned int cam_flags,
+	struct dma_buf **buf)
+{
+	int rc = 0;
+	struct dma_heap *heap;
+	struct dma_heap *try_heap = NULL;
+	struct timespec64 ts1, ts2;
+	long microsec = 0;
+	bool use_cached_heap = false;
+
+	if (!buf) {
+		CAM_ERR(CAM_MEM, "Invalid params");
+		return -EINVAL;
+	}
+
+	if (tbl.alloc_profile_enable)
+		CAM_GET_TIMESTAMP(ts1);
+
+	if ((cam_flags & CAM_MEM_FLAG_CACHE) ||
+		(tbl.force_cache_allocs &&
+		(!(cam_flags & CAM_MEM_FLAG_PROTECTED_MODE)))) {
+		CAM_DBG(CAM_MEM,
+			"Using CACHED heap, cam_flags=0x%x, force_cache_allocs=%d",
+			cam_flags, tbl.force_cache_allocs);
+		use_cached_heap = true;
+	} else if (cam_flags & CAM_MEM_FLAG_PROTECTED_MODE) {
+		use_cached_heap = true;
+		CAM_DBG(CAM_MEM,
+			"Using CACHED heap for secure, cam_flags=0x%x, force_cache_allocs=%d",
+			cam_flags, tbl.force_cache_allocs);
+	} else {
+		use_cached_heap = false;
+		CAM_ERR(CAM_MEM,
+			"Using UNCACHED heap not supported, cam_flags=0x%x, force_cache_allocs=%d",
+			cam_flags, tbl.force_cache_allocs);
+		/*
+		 * Need a better handling based on whether dma-buf-heaps support
+		 * uncached heaps or not. For now, assume not supported.
+		 */
+		return -EINVAL;
+	}
+
+	if ((cam_flags & CAM_MEM_FLAG_PROTECTED_MODE) &&
+		(cam_flags & CAM_MEM_FLAG_CDSP_OUTPUT)) {
+		heap = tbl.secure_display_heap;
+		CAM_ERR(CAM_MEM, "Secure CDSP not supported yet");
+		return -EBADR;
+	} else if (cam_flags & CAM_MEM_FLAG_PROTECTED_MODE) {
+		heap = tbl.secure_display_heap;
+		CAM_ERR(CAM_MEM, "Secure mode not supported yet");
+		return -EBADR;
+	}
+
+	if (use_cached_heap) {
+		try_heap = tbl.camera_heap;
+		heap = tbl.system_heap;
+	} else {
+		try_heap = tbl.camera_uncached_heap;
+		heap = tbl.system_uncached_heap;
+	}
+
+	CAM_DBG(CAM_MEM, "Using heaps : try=%pK, heap=%pK", try_heap, heap);
+
+	*buf = NULL;
+
+	if (!try_heap && !heap) {
+		CAM_ERR(CAM_MEM,
+			"No heap available for allocation, cant allocate");
+		return -EINVAL;
+	}
+
+	if (try_heap) {
+		*buf = dma_heap_buffer_alloc(try_heap, len, O_RDWR, 0);
+		if (IS_ERR_OR_NULL(*buf)) {
+			CAM_WARN(CAM_MEM,
+				"Failed in allocating from try heap, heap=%pK, len=%zu, err=%d",
+				try_heap, len, PTR_ERR(*buf));
+			*buf = NULL;
+		}
+	}
+
+	if (*buf == NULL) {
+		*buf = dma_heap_buffer_alloc(heap, len, O_RDWR, 0);
+		if (IS_ERR_OR_NULL(*buf)) {
+			rc = PTR_ERR(*buf);
+			CAM_ERR(CAM_MEM,
+				"Failed in allocating from heap, heap=%pK, len=%zu, err=%d",
+				heap, len, rc);
+			*buf = NULL;
+			return rc;
+		}
+	}
+
+	CAM_DBG(CAM_MEM, "Allocate success, len=%zu, *buf=%pK", len, *buf);
+
+	if (tbl.alloc_profile_enable) {
+		CAM_GET_TIMESTAMP(ts2);
+		CAM_GET_TIMESTAMP_DIFF_IN_MICRO(ts1, ts2, microsec);
+		trace_cam_log_event("IONAllocProfile", "size and time in micro",
+			len, microsec);
+	}
+
+	return rc;
+}
+#else
 static int cam_mem_util_get_dma_buf(size_t len,
 static int cam_mem_util_get_dma_buf(size_t len,
 	unsigned int cam_flags,
 	unsigned int cam_flags,
 	struct dma_buf **buf)
 	struct dma_buf **buf)
@@ -460,8 +670,9 @@ static int cam_mem_util_get_dma_buf(size_t len,
 
 
 	return rc;
 	return rc;
 }
 }
+#endif
 
 
-static int cam_mem_util_ion_alloc(struct cam_mem_mgr_alloc_cmd *cmd,
+static int cam_mem_util_buffer_alloc(struct cam_mem_mgr_alloc_cmd *cmd,
 	struct dma_buf **dmabuf,
 	struct dma_buf **dmabuf,
 	int *fd)
 	int *fd)
 {
 {
@@ -485,6 +696,9 @@ static int cam_mem_util_ion_alloc(struct cam_mem_mgr_alloc_cmd *cmd,
 		goto put_buf;
 		goto put_buf;
 	}
 	}
 
 
+	CAM_DBG(CAM_MEM, "Alloc success : len=%zu, *dmabuf=%pK, fd=%d",
+		cmd->len, *dmabuf, *fd);
+
 	/*
 	/*
 	 * increment the ref count so that ref count becomes 2 here
 	 * increment the ref count so that ref count becomes 2 here
 	 * when we close fd, refcount becomes 1 and when we do
 	 * when we close fd, refcount becomes 1 and when we do
@@ -655,7 +869,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd)
 		return rc;
 		return rc;
 	}
 	}
 
 
-	rc = cam_mem_util_ion_alloc(cmd,
+	rc = cam_mem_util_buffer_alloc(cmd,
 		&dmabuf,
 		&dmabuf,
 		&fd);
 		&fd);
 	if (rc) {
 	if (rc) {

+ 12 - 1
drivers/cam_req_mgr/cam_mem_mgr.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _CAM_MEM_MGR_H_
 #ifndef _CAM_MEM_MGR_H_
@@ -8,6 +8,9 @@
 
 
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/dma-buf.h>
 #include <linux/dma-buf.h>
+#if IS_REACHABLE(CONFIG_DMABUF_HEAPS)
+#include <linux/dma-heap.h>
+#endif
 #include <media/cam_req_mgr.h>
 #include <media/cam_req_mgr.h>
 #include "cam_mem_mgr_api.h"
 #include "cam_mem_mgr_api.h"
 
 
@@ -81,6 +84,14 @@ struct cam_mem_table {
 	bool alloc_profile_enable;
 	bool alloc_profile_enable;
 	size_t dbg_buf_idx;
 	size_t dbg_buf_idx;
 	bool force_cache_allocs;
 	bool force_cache_allocs;
+#if IS_REACHABLE(CONFIG_DMABUF_HEAPS)
+	struct dma_heap *system_heap;
+	struct dma_heap *system_uncached_heap;
+	struct dma_heap *camera_heap;
+	struct dma_heap *camera_uncached_heap;
+	struct dma_heap *secure_display_heap;
+#endif
+
 };
 };
 
 
 /**
 /**

+ 7 - 5
drivers/cam_smmu/cam_smmu_api.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -2100,8 +2100,9 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf,
 	}
 	}
 
 
 	CAM_DBG(CAM_SMMU,
 	CAM_DBG(CAM_SMMU,
-		"iova=%pK, region_id=%d, paddr=%pK, len=%d, dma_map_attrs=%d",
-		iova, region_id, *paddr_ptr, *len_ptr, attach->dma_map_attrs);
+		"iova=%pK, region_id=%d, paddr=0x%x, len=%d, dma_map_attrs=%d",
+		iova, region_id, (uint64_t)*paddr_ptr, *len_ptr,
+		attach->dma_map_attrs);
 
 
 	if (iommu_cb_set.map_profile_enable) {
 	if (iommu_cb_set.map_profile_enable) {
 		CAM_GET_TIMESTAMP(ts2);
 		CAM_GET_TIMESTAMP(ts2);
@@ -2148,7 +2149,8 @@ static int cam_smmu_map_buffer_validate(struct dma_buf *buf,
 		rc = -ENOSPC;
 		rc = -ENOSPC;
 		goto err_alloc;
 		goto err_alloc;
 	}
 	}
-	CAM_DBG(CAM_SMMU, "idx=%d, dma_buf=%pK, dev=%pK, paddr=%pK, len=%u",
+
+	CAM_DBG(CAM_SMMU, "idx=%d, dma_buf=%pK, dev=%pK, paddr=0x%x, len=%u",
 		idx, buf, (void *)iommu_cb_set.cb_info[idx].dev,
 		idx, buf, (void *)iommu_cb_set.cb_info[idx].dev,
 		(void *)*paddr_ptr, (unsigned int)*len_ptr);
 		(void *)*paddr_ptr, (unsigned int)*len_ptr);
 
 
@@ -2267,7 +2269,7 @@ static int cam_smmu_unmap_buf_and_remove_from_list(
 		mapping_info);
 		mapping_info);
 
 
 	CAM_DBG(CAM_SMMU,
 	CAM_DBG(CAM_SMMU,
-		"region_id=%d, paddr=%pK, len=%d, dma_map_attrs=%d",
+		"region_id=%d, paddr=0x%x, len=%d, dma_map_attrs=%d",
 		mapping_info->region_id, mapping_info->paddr, mapping_info->len,
 		mapping_info->region_id, mapping_info->paddr, mapping_info->len,
 		mapping_info->attach->dma_map_attrs);
 		mapping_info->attach->dma_map_attrs);