Merge "msm: camera: smmu: Add map and unmap monitor" into camera-kernel.lnx.4.0

This commit is contained in:
Camera Software Integration 2020-05-04 14:06:05 -07:00 • committed by Gerrit - the friendly Code Review server
commit c056e39f34

View file

@ -42,6 +42,11 @@
#define GET_SMMU_HDL(x, y) (((x) << COOKIE_SIZE) | ((y) & COOKIE_MASK))
#define GET_SMMU_TABLE_IDX(x) (((x) >> COOKIE_SIZE) & COOKIE_MASK)
#define CAM_SMMU_MONITOR_MAX_ENTRIES 100
#define CAM_SMMU_INC_MONITOR_HEAD(head, ret) \
div_u64_rem(atomic64_add_return(1, head),\
CAM_SMMU_MONITOR_MAX_ENTRIES, (ret))
static int g_num_pf_handled = 4;
module_param(g_num_pf_handled, int, 0644);
@ -94,6 +99,17 @@ struct secheap_buf_info {
struct sg_table *table;
};
struct cam_smmu_monitor {
struct timespec64 timestamp;
bool is_map;
/* map-unmap info */
int ion_fd;
dma_addr_t paddr;
size_t len;
enum cam_smmu_region_id region_id;
};
struct cam_context_bank_info {
struct device *dev;
struct iommu_domain *domain;
@ -143,6 +159,9 @@ struct cam_context_bank_info {
/* discard iova - non-zero values are valid */
dma_addr_t discard_iova_start;
size_t discard_iova_len;
atomic64_t monitor_head;
struct cam_smmu_monitor monitor_entries[CAM_SMMU_MONITOR_MAX_ENTRIES];
};
struct cam_iommu_cb_set {
@ -266,6 +285,76 @@ static int cam_smmu_probe(struct platform_device *pdev);
static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr);
static void cam_smmu_update_monitor_array(
struct cam_context_bank_info *cb_info,
bool is_map,
struct cam_dma_buff_info *mapping_info)
{
int iterator;
CAM_SMMU_INC_MONITOR_HEAD(&cb_info->monitor_head, &iterator);
ktime_get_real_ts64(&cb_info->monitor_entries[iterator].timestamp);
cb_info->monitor_entries[iterator].is_map = is_map;
cb_info->monitor_entries[iterator].ion_fd = mapping_info->ion_fd;
cb_info->monitor_entries[iterator].paddr = mapping_info->paddr;
cb_info->monitor_entries[iterator].len = mapping_info->len;
cb_info->monitor_entries[iterator].region_id = mapping_info->region_id;
}
static void cam_smmu_dump_monitor_array(
struct cam_context_bank_info *cb_info)
{
int i = 0;
int64_t state_head = 0;
uint32_t index, num_entries, oldest_entry;
uint64_t ms, tmp, hrs, min, sec;
struct timespec64 *ts = NULL;
state_head = atomic64_read(&cb_info->monitor_head);
if (state_head == -1) {
return;
} else if (state_head < CAM_SMMU_MONITOR_MAX_ENTRIES) {
num_entries = state_head;
oldest_entry = 0;
} else {
num_entries = CAM_SMMU_MONITOR_MAX_ENTRIES;
div_u64_rem(state_head + 1,
CAM_SMMU_MONITOR_MAX_ENTRIES, &oldest_entry);
}
CAM_INFO(CAM_SMMU,
"========Dumping monitor information for cb %s===========",
cb_info->name[0]);
index = oldest_entry;
for (i = 0; i < num_entries; i++) {
ts = &cb_info->monitor_entries[index].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_SMMU,
"**** %llu:%llu:%llu.%llu : Index[%d] [%s] : ion_fd=%d start=0x%x end=0x%x len=%u region=%d",
hrs, min, sec, ms,
index,
cb_info->monitor_entries[index].is_map ? "MAP" : "UNMAP",
cb_info->monitor_entries[index].ion_fd,
(void *)cb_info->monitor_entries[index].paddr,
((uint64_t)cb_info->monitor_entries[index].paddr +
(uint64_t)cb_info->monitor_entries[index].len),
(unsigned int)cb_info->monitor_entries[index].len,
cb_info->monitor_entries[index].region_id);
index = (index + 1) % CAM_SMMU_MONITOR_MAX_ENTRIES;
}
}
static void cam_smmu_page_fault_work(struct work_struct *work)
{
int j;
@ -328,7 +417,7 @@ static void cam_smmu_dump_cb_info(int idx)
CAM_ERR(CAM_SMMU,
"********** Context bank dump for %s **********",
cb_info->name);
cb_info->name[0]);
CAM_ERR(CAM_SMMU,
"Usage: shared_usage=%u io_usage=%u shared_free=%u io_free=%u",
(unsigned int)cb_info->shared_mapping_size,
@ -348,6 +437,8 @@ static void cam_smmu_dump_cb_info(int idx)
(unsigned int)mapping->len,
mapping->region_id);
}
cam_smmu_dump_monitor_array(&iommu_cb_set.cb_info[idx]);
}
}
@ -1928,6 +2019,9 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd,
list_add(&mapping_info->list,
&iommu_cb_set.cb_info[idx].smmu_buf_list);
cam_smmu_update_monitor_array(&iommu_cb_set.cb_info[idx], true,
mapping_info);
return 0;
}
@ -1953,6 +2047,9 @@ static int cam_smmu_map_kernel_buffer_and_add_to_list(int idx,
list_add(&mapping_info->list,
&iommu_cb_set.cb_info[idx].smmu_buf_kernel_list);
cam_smmu_update_monitor_array(&iommu_cb_set.cb_info[idx], true,
mapping_info);
return 0;
}
@ -1979,6 +2076,9 @@ static int cam_smmu_unmap_buf_and_remove_from_list(
return -EINVAL;
}
cam_smmu_update_monitor_array(&iommu_cb_set.cb_info[idx], false,
mapping_info);
CAM_DBG(CAM_SMMU,
"region_id=%d, paddr=%pK, len=%d, dma_map_attrs=%d",
mapping_info->region_id, mapping_info->paddr, mapping_info->len,
@ -2948,6 +3048,7 @@ int cam_smmu_get_iova(int handle, int ion_fd,
if (buf_state == CAM_SMMU_BUFF_NOT_EXIST) {
CAM_ERR(CAM_SMMU, "ion_fd:%d not in the mapped list", ion_fd);
rc = -EINVAL;
cam_smmu_dump_cb_info(idx);
goto get_addr_end;
}
@ -3305,6 +3406,8 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb,
cb->is_fw_allocated = false;
cb->is_secheap_allocated = false;
atomic64_set(&cb->monitor_head, -1);
/* Create a pool with 64K granularity for supporting shared memory */
if (cb->shared_support) {
cb->shared_mem_pool = gen_pool_create(
@ -3638,7 +3741,7 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node,
cb->io_info.iova_start + cb->io_info.iova_len)) {
CAM_ERR(CAM_SMMU,
"[%s] : Incorrect Discard region specified [0x%x 0x%x] in [0x%x 0x%x]",
cb->name,
cb->name[0],
cb->discard_iova_start,
cb->discard_iova_start + cb->discard_iova_len,
cb->io_info.iova_start,
@ -3649,7 +3752,7 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node,
CAM_INFO(CAM_SMMU,
"[%s] : Discard region specified [0x%x 0x%x] in [0x%x 0x%x]",
cb->name,
cb->name[0],
cb->discard_iova_start,
cb->discard_iova_start + cb->discard_iova_len,
cb->io_info.iova_start,