Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf4afca1 authored by Camera Software Integration's avatar Camera Software Integration Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: smmu: Enhance debug capability for camera memmgr" into camera-kernel.lnx.1.0

parents e46741c3 5edad40f
Loading
Loading
Loading
Loading
+56 −8
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-License-Identifier: GPL-2.0-only
/*
/*
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 */
 */


#include <linux/module.h>
#include <linux/module.h>
@@ -22,6 +22,39 @@
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);


static void cam_mem_mgr_print_tbl(void)
{
	int i;
	uint64_t ms, tmp, hrs, min, sec;
	struct timespec64 *ts =  NULL;
	struct timespec64 current_ts;

	ktime_get_real_ts64(&(current_ts));
	tmp = current_ts.tv_sec;
	ms = (current_ts.tv_nsec) / 1000000;
	sec = do_div(tmp, 60);
	min = do_div(tmp, 60);
	hrs = do_div(tmp, 24);

	CAM_INFO(CAM_MEM, "***%llu:%llu:%llu:%llu Mem mgr table dump***",
		hrs, min, sec, ms);
	for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) {
		if (tbl.bufq[i].active) {
			ts = &tbl.bufq[i].timestamp;
			tmp = ts->tv_sec;
			ms = (ts->tv_nsec) / 1000000;
			sec = do_div(tmp, 60);
			min = do_div(tmp, 60);
			hrs = do_div(tmp, 24);
			CAM_INFO(CAM_MEM,
				"%llu:%llu:%llu:%llu idx %d fd %d size %llu",
				hrs, min, sec, ms, i, tbl.bufq[i].fd,
				tbl.bufq[i].len);
		}
	}

}

static int cam_mem_util_get_dma_dir(uint32_t flags)
static int cam_mem_util_get_dma_dir(uint32_t flags)
{
{
	int rc = -EINVAL;
	int rc = -EINVAL;
@@ -185,6 +218,7 @@ static int32_t cam_mem_get_slot(void)


	set_bit(idx, tbl.bitmap);
	set_bit(idx, tbl.bitmap);
	tbl.bufq[idx].active = true;
	tbl.bufq[idx].active = true;
	ktime_get_real_ts64(&(tbl.bufq[idx].timestamp));
	mutex_init(&tbl.bufq[idx].q_lock);
	mutex_init(&tbl.bufq[idx].q_lock);
	mutex_unlock(&tbl.m_lock);
	mutex_unlock(&tbl.m_lock);


@@ -196,6 +230,7 @@ static void cam_mem_put_slot(int32_t idx)
	mutex_lock(&tbl.m_lock);
	mutex_lock(&tbl.m_lock);
	mutex_lock(&tbl.bufq[idx].q_lock);
	mutex_lock(&tbl.bufq[idx].q_lock);
	tbl.bufq[idx].active = false;
	tbl.bufq[idx].active = false;
	memset(&tbl.bufq[idx].timestamp, 0, sizeof(struct timespec64));
	mutex_unlock(&tbl.bufq[idx].q_lock);
	mutex_unlock(&tbl.bufq[idx].q_lock);
	mutex_destroy(&tbl.bufq[idx].q_lock);
	mutex_destroy(&tbl.bufq[idx].q_lock);
	clear_bit(idx, tbl.bitmap);
	clear_bit(idx, tbl.bitmap);
@@ -643,6 +678,7 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd)
		CAM_ERR(CAM_MEM,
		CAM_ERR(CAM_MEM,
			"Ion Alloc failed, len=%llu, align=%llu, flags=0x%x, num_hdl=%d",
			"Ion Alloc failed, len=%llu, align=%llu, flags=0x%x, num_hdl=%d",
			cmd->len, cmd->align, cmd->flags, cmd->num_hdl);
			cmd->len, cmd->align, cmd->flags, cmd->num_hdl);
		cam_mem_mgr_print_tbl();
		return rc;
		return rc;
	}
	}


@@ -679,9 +715,14 @@ int cam_mem_mgr_alloc_and_map(struct cam_mem_mgr_alloc_cmd *cmd)


		if (rc) {
		if (rc) {
			CAM_ERR(CAM_MEM,
			CAM_ERR(CAM_MEM,
				"Failed in map_hw_va, len=%llu, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d",
				"Failed in map_hw_va, [Size cmdlen=%llu dma %llu smmu %llu], flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d",
				cmd->len, cmd->flags, fd, region,
				cmd->len, dmabuf->size, len, cmd->flags,
				cmd->num_hdl, rc);
				fd, region, cmd->num_hdl, rc);
			if (rc == -EALREADY) {
				if ((size_t)dmabuf->size != len)
					rc = -EBADR;
				cam_mem_mgr_print_tbl();
			}
			goto map_hw_fail;
			goto map_hw_fail;
		}
		}
	}
	}
@@ -780,9 +821,15 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd)
			CAM_SMMU_REGION_IO);
			CAM_SMMU_REGION_IO);
		if (rc) {
		if (rc) {
			CAM_ERR(CAM_MEM,
			CAM_ERR(CAM_MEM,
				"Failed in map_hw_va, flags=0x%x, fd=%d, region=%d, num_hdl=%d, rc=%d",
				"Failed in map_hw_va, flags=0x%x, fd=%d, [Size smmu %llu dma %llu], region=%d, num_hdl=%d, rc=%d",
				cmd->flags, cmd->fd, CAM_SMMU_REGION_IO,
				cmd->flags, cmd->fd, len, dmabuf->size,
				cmd->num_hdl, rc);
				CAM_SMMU_REGION_IO, cmd->num_hdl, rc);
			if (rc == -EALREADY) {
				if ((size_t)dmabuf->size != len) {
					rc = -EBADR;
					cam_mem_mgr_print_tbl();
				}
			}
			goto map_fail;
			goto map_fail;
		}
		}
	}
	}
@@ -817,7 +864,7 @@ int cam_mem_mgr_map(struct cam_mem_mgr_map_cmd *cmd)


	cmd->out.buf_handle = tbl.bufq[idx].buf_handle;
	cmd->out.buf_handle = tbl.bufq[idx].buf_handle;
	cmd->out.vaddr = 0;
	cmd->out.vaddr = 0;

	cmd->out.size = (uint32_t)len;
	CAM_DBG(CAM_MEM,
	CAM_DBG(CAM_MEM,
		"fd=%d, flags=0x%x, num_hdl=%d, idx=%d, buf handle=%x, len=%zu",
		"fd=%d, flags=0x%x, num_hdl=%d, idx=%d, buf handle=%x, len=%zu",
		cmd->fd, cmd->flags, cmd->num_hdl, idx, cmd->out.buf_handle,
		cmd->fd, cmd->flags, cmd->num_hdl, idx, cmd->out.buf_handle,
@@ -1037,6 +1084,7 @@ static int cam_mem_util_unmap(int32_t idx,
	tbl.bufq[idx].len = 0;
	tbl.bufq[idx].len = 0;
	tbl.bufq[idx].num_hdl = 0;
	tbl.bufq[idx].num_hdl = 0;
	tbl.bufq[idx].active = false;
	tbl.bufq[idx].active = false;
	memset(&tbl.bufq[idx].timestamp, 0, sizeof(struct timespec64));
	mutex_unlock(&tbl.bufq[idx].q_lock);
	mutex_unlock(&tbl.bufq[idx].q_lock);
	mutex_destroy(&tbl.bufq[idx].q_lock);
	mutex_destroy(&tbl.bufq[idx].q_lock);
	clear_bit(idx, tbl.bitmap);
	clear_bit(idx, tbl.bitmap);
+3 −1
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/* SPDX-License-Identifier: GPL-2.0-only */
/*
/*
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
 */
 */


#ifndef _CAM_MEM_MGR_H_
#ifndef _CAM_MEM_MGR_H_
@@ -41,6 +41,7 @@ enum cam_smmu_mapping_client {
 * @kmdvaddr:    Kernel virtual address
 * @kmdvaddr:    Kernel virtual address
 * @active:      state of the buffer
 * @active:      state of the buffer
 * @is_imported: Flag indicating if buffer is imported from an FD in user space
 * @is_imported: Flag indicating if buffer is imported from an FD in user space
 * @timestamp:   Timestamp at which this entry in tbl was made
 */
 */
struct cam_mem_buf_queue {
struct cam_mem_buf_queue {
	struct dma_buf *dma_buf;
	struct dma_buf *dma_buf;
@@ -56,6 +57,7 @@ struct cam_mem_buf_queue {
	uintptr_t kmdvaddr;
	uintptr_t kmdvaddr;
	bool active;
	bool active;
	bool is_imported;
	bool is_imported;
	struct timespec64 timestamp;
};
};


/**
/**
+50 −12
Original line number Original line Diff line number Diff line
@@ -196,6 +196,7 @@ struct cam_dma_buff_info {
	int ion_fd;
	int ion_fd;
	size_t len;
	size_t len;
	size_t phys_len;
	size_t phys_len;
	struct timespec64 ts;
};
};


struct cam_sec_buff_info {
struct cam_sec_buff_info {
@@ -401,6 +402,9 @@ static void cam_smmu_dump_cb_info(int idx)
	size_t shared_reg_len = 0, io_reg_len = 0;
	size_t shared_reg_len = 0, io_reg_len = 0;
	size_t shared_free_len = 0, io_free_len = 0;
	size_t shared_free_len = 0, io_free_len = 0;
	uint32_t i = 0;
	uint32_t i = 0;
	uint64_t ms, tmp, hrs, min, sec;
	struct timespec64 *ts = NULL;
	struct timespec64 current_ts;
	struct cam_context_bank_info *cb_info =
	struct cam_context_bank_info *cb_info =
		&iommu_cb_set.cb_info[idx];
		&iommu_cb_set.cb_info[idx];


@@ -414,9 +418,15 @@ static void cam_smmu_dump_cb_info(int idx)
		io_free_len = io_reg_len - cb_info->io_mapping_size;
		io_free_len = io_reg_len - cb_info->io_mapping_size;
	}
	}


	ktime_get_real_ts64(&(current_ts));
	tmp = current_ts.tv_sec;
	ms = (current_ts.tv_nsec) / 1000000;
	sec = do_div(tmp, 60);
	min = do_div(tmp, 60);
	hrs = do_div(tmp, 24);
	CAM_ERR(CAM_SMMU,
	CAM_ERR(CAM_SMMU,
		"********** Context bank dump for %s **********",
		"********** %llu:%llu:%llu:%llu Context bank dump for %s **********",
		cb_info->name);
		hrs, min, sec, ms, cb_info->name);
	CAM_ERR(CAM_SMMU,
	CAM_ERR(CAM_SMMU,
		"Usage: shared_usage=%u io_usage=%u shared_free=%u io_free=%u",
		"Usage: shared_usage=%u io_usage=%u shared_free=%u io_free=%u",
		(unsigned int)cb_info->shared_mapping_size,
		(unsigned int)cb_info->shared_mapping_size,
@@ -428,9 +438,16 @@ static void cam_smmu_dump_cb_info(int idx)
		list_for_each_entry_safe(mapping, mapping_temp,
		list_for_each_entry_safe(mapping, mapping_temp,
			&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
			&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
			i++;
			i++;
			ts = &mapping->ts;
			tmp = ts->tv_sec;
			ms = (ts->tv_nsec) / 1000000;
			sec = do_div(tmp, 60);
			min = do_div(tmp, 60);
			hrs = do_div(tmp, 24);
			CAM_ERR(CAM_SMMU,
			CAM_ERR(CAM_SMMU,
				"%u. ion_fd=%d start=0x%x end=0x%x len=%u region=%d",
				"%llu:%llu:%llu:%llu: %u ion_fd=%d start=0x%x end=0x%x len=%u region=%d",
				i, mapping->ion_fd, (void *)mapping->paddr,
				hrs, min, sec, ms, i, mapping->ion_fd,
				(void *)mapping->paddr,
				((uint64_t)mapping->paddr +
				((uint64_t)mapping->paddr +
				(uint64_t)mapping->len),
				(uint64_t)mapping->len),
				(unsigned int)mapping->len,
				(unsigned int)mapping->len,
@@ -1999,6 +2016,7 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd,
	}
	}


	mapping_info->ion_fd = ion_fd;
	mapping_info->ion_fd = ion_fd;
	ktime_get_real_ts64(&mapping_info->ts);
	/* add to the list */
	/* add to the list */
	list_add(&mapping_info->list,
	list_add(&mapping_info->list,
		&iommu_cb_set.cb_info[idx].smmu_buf_list);
		&iommu_cb_set.cb_info[idx].smmu_buf_list);
@@ -2026,7 +2044,7 @@ static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx,
	}
	}


	mapping_info->ion_fd = -1;
	mapping_info->ion_fd = -1;

	ktime_get_real_ts64(&mapping_info->ts);
	/* add to the list */
	/* add to the list */
	list_add(&mapping_info->list,
	list_add(&mapping_info->list,
		&iommu_cb_set.cb_info[idx].smmu_buf_kernel_list);
		&iommu_cb_set.cb_info[idx].smmu_buf_kernel_list);
@@ -2124,15 +2142,28 @@ static int cam_smmu_unmap_buf_and_remove_from_list(
}
}


static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx,
static enum cam_smmu_buf_state cam_smmu_check_fd_in_list(int idx,
	int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr)
	int ion_fd, dma_addr_t *paddr_ptr, size_t *len_ptr, size_t *dma_buf_len)
{
{
	struct cam_dma_buff_info *mapping;
	struct cam_dma_buff_info *mapping;
	struct timespec64 *ts = NULL;
	uint64_t ms, tmp, hrs, min, sec;


	list_for_each_entry(mapping,
	list_for_each_entry(mapping,
		&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
		&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
		if (mapping->ion_fd == ion_fd) {
		if (mapping->ion_fd == ion_fd) {
			*paddr_ptr = mapping->paddr;
			*paddr_ptr = mapping->paddr;
			*len_ptr = mapping->len;
			*len_ptr = mapping->len;
			*dma_buf_len = mapping->buf->size;
			ts = &mapping->ts;
			tmp = ts->tv_sec;
			ms = (ts->tv_nsec) / 1000000;
			sec = do_div(tmp, 60);
			min = do_div(tmp, 60);
			hrs = do_div(tmp, 24);
			CAM_WARN(CAM_SMMU,
				"Mapping found ts %llu:%llu:%llu:%llu paddr 0x%p len %llu dma_len %llu",
				hrs, min, sec, ms, (void *)mapping->paddr,
				mapping->len, *dma_buf_len);
			return CAM_SMMU_BUFF_EXIST;
			return CAM_SMMU_BUFF_EXIST;
		}
		}
	}
	}
@@ -2863,6 +2894,7 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap,
	size_t *len_ptr, enum cam_smmu_region_id region_id)
	size_t *len_ptr, enum cam_smmu_region_id region_id)
{
{
	int idx, rc = 0;
	int idx, rc = 0;
	size_t dma_len = 0;
	enum cam_smmu_buf_state buf_state;
	enum cam_smmu_buf_state buf_state;
	enum dma_data_direction dma_dir;
	enum dma_data_direction dma_dir;


@@ -2900,11 +2932,14 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap,
		goto get_addr_end;
		goto get_addr_end;
	}
	}


	buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr);
	buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr,
		len_ptr, &dma_len);
	if (buf_state == CAM_SMMU_BUFF_EXIST) {
	if (buf_state == CAM_SMMU_BUFF_EXIST) {
		CAM_ERR(CAM_SMMU,
		CAM_ERR(CAM_SMMU,
			"fd:%d already in list idx:%d, handle=%d, give same addr back",
			"fd:%d already in list cb:%s idx:%d handle=%d len=%llu dma_len=%llu, give same addr back",
			ion_fd, idx, handle);
			ion_fd, iommu_cb_set.cb_info[idx].name,
			idx, handle, *len_ptr, dma_len);
		*len_ptr = dma_len;
		rc = -EALREADY;
		rc = -EALREADY;
		goto get_addr_end;
		goto get_addr_end;
	}
	}
@@ -2913,8 +2948,9 @@ int cam_smmu_map_user_iova(int handle, int ion_fd, bool dis_delayed_unmap,
		dis_delayed_unmap, dma_dir, paddr_ptr, len_ptr, region_id);
		dis_delayed_unmap, dma_dir, paddr_ptr, len_ptr, region_id);
	if (rc < 0) {
	if (rc < 0) {
		CAM_ERR(CAM_SMMU,
		CAM_ERR(CAM_SMMU,
			"mapping or add list fail, idx=%d, fd=%d, region=%d, rc=%d",
			"mapping or add list fail cb:%s idx=%d, fd=%d, region=%d, rc=%d",
			idx, ion_fd, region_id, rc);
			iommu_cb_set.cb_info[idx].name, idx,
			ion_fd, region_id, rc);
		cam_smmu_dump_cb_info(idx);
		cam_smmu_dump_cb_info(idx);
	}
	}


@@ -2988,6 +3024,7 @@ int cam_smmu_get_iova(int handle, int ion_fd,
	dma_addr_t *paddr_ptr, size_t *len_ptr)
	dma_addr_t *paddr_ptr, size_t *len_ptr)
{
{
	int idx, rc = 0;
	int idx, rc = 0;
	size_t dma_buf_size = 0;
	enum cam_smmu_buf_state buf_state;
	enum cam_smmu_buf_state buf_state;


	if (!paddr_ptr || !len_ptr) {
	if (!paddr_ptr || !len_ptr) {
@@ -3027,7 +3064,8 @@ int cam_smmu_get_iova(int handle, int ion_fd,
		goto get_addr_end;
		goto get_addr_end;
	}
	}


	buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr, len_ptr);
	buf_state = cam_smmu_check_fd_in_list(idx, ion_fd, paddr_ptr,
		len_ptr, &dma_buf_size);
	if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) {
	if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) {
		CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd);
		CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd);
		rc = -EINVAL;
		rc = -EINVAL;
+2 −2
Original line number Original line Diff line number Diff line
@@ -341,12 +341,12 @@ struct cam_mem_alloc_out_params {
/**
/**
 * struct cam_mem_map_out_params
 * struct cam_mem_map_out_params
 * @buf_handle: buffer handle
 * @buf_handle: buffer handle
 * @reserved: reserved for future
 * @size: size of the buffer being mapped
 * @vaddr: virtual address pointer
 * @vaddr: virtual address pointer
 */
 */
struct cam_mem_map_out_params {
struct cam_mem_map_out_params {
	uint32_t buf_handle;
	uint32_t buf_handle;
	uint32_t reserved;
	uint32_t size;
	uint64_t vaddr;
	uint64_t vaddr;
};
};