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 <pchilamk@codeaurora.org>
This commit is contained in:
Pavan Kumar Chilamkurthi
2020-11-23 01:58:38 -08:00
parent 7f497cf736
commit 68eda98831
3 changed files with 239 additions and 12 deletions

View File

@@ -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) if (!tbl.bitmap) {
return -ENOMEM; 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) {

View File

@@ -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
}; };
/** /**

View File

@@ -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=%pK, region_id=%d, paddr=0x%x, len=%d, dma_map_attrs=%d",
iova, region_id, *paddr_ptr, *len_ptr, attach->dma_map_attrs); 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);