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

Commit ab5a6389 authored by Ravikishore Pampana's avatar Ravikishore Pampana
Browse files

msm: camera: jpeg: Handle JPEG smmu fault with pid info



Kernel apis provide information fault caused pid and mid data.
Handle the JPEG smmu fault using pid and mid
data. Based on the mid data, dump only corresponding port
info which caused the fault. Pid and mid values are target
dependent, these values will be updated on the jpeg node
dt entries.

CRs-Fixed: 2878371
Change-Id: I0d2d1e474d4662707d85efd022ccce87e67f0d93
Signed-off-by: default avatarRavikishore Pampana <rpampana@codeaurora.org>
parent d0e2538e
Loading
Loading
Loading
Loading
+118 −76
Original line number Diff line number Diff line
@@ -694,75 +694,6 @@ static int cam_jpeg_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
	return rc;
}

static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet,
	int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info,
	bool *mem_found)
{
	dma_addr_t   iova_addr;
	size_t     src_buf_size;
	int        i;
	int        j;
	int        rc = 0;
	int32_t    mmu_hdl;
	struct cam_buf_io_cfg  *io_cfg = NULL;

	if (mem_found)
		*mem_found = false;

	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
		packet->io_configs_offset / 4);

	for (i = 0; i < packet->num_io_configs; i++) {
		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
			if (!io_cfg[i].mem_handle[j])
				break;

			if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
				GET_FD_FROM_HANDLE(pf_buf_info)) {
				CAM_INFO(CAM_JPEG,
					"Found PF at port: %d mem %x fd: %x",
					io_cfg[i].resource_type,
					io_cfg[i].mem_handle[j],
					pf_buf_info);
				if (mem_found)
					*mem_found = true;
			}

			CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d",
				io_cfg[i].resource_type,
				io_cfg[i].fence,
				io_cfg[i].format,
				io_cfg[i].direction);

			mmu_hdl = cam_mem_is_secure_buf(
				io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
				iommu_hdl;
			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
				mmu_hdl, &iova_addr, &src_buf_size);
			if (rc < 0) {
				CAM_ERR(CAM_UTIL, "get src buf address fail");
				continue;
			}
			if ((iova_addr & 0xFFFFFFFF) != iova_addr) {
				CAM_ERR(CAM_JPEG, "Invalid mapped address");
				rc = -EINVAL;
				continue;
			}

			CAM_INFO(CAM_JPEG,
				"pln %u w %u h %u stride %u slice %u size %d addr 0x%x offset 0x%x memh %x",
				j, io_cfg[i].planes[j].width,
				io_cfg[i].planes[j].height,
				io_cfg[i].planes[j].plane_stride,
				io_cfg[i].planes[j].slice_height,
				(int32_t)src_buf_size,
				(unsigned int)iova_addr,
				io_cfg[i].offsets[j],
				io_cfg[i].mem_handle[j]);
		}
	}
}

static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv,
	void *prepare_hw_update_args)
{
@@ -1570,6 +1501,18 @@ static int cam_jpeg_init_devices(struct device_node *of_node,
	g_jpeg_hw_mgr.cdm_reg_map[CAM_JPEG_DEV_DMA][0] =
		&dma_soc_info->reg_map[0];

	rc = g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC][0]->hw_ops.process_cmd(
		g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_ENC][0]->hw_priv,
		CAM_JPEG_CMD_GET_NUM_PID,
		&g_jpeg_hw_mgr.num_pid[CAM_JPEG_DEV_ENC],
		sizeof(uint32_t));

	rc = g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA][0]->hw_ops.process_cmd(
		g_jpeg_hw_mgr.devices[CAM_JPEG_DEV_DMA][0]->hw_priv,
		CAM_JPEG_CMD_GET_NUM_PID,
		&g_jpeg_hw_mgr.num_pid[CAM_JPEG_DEV_DMA],
		sizeof(uint32_t));

	*p_num_enc_dev = num_dev;
	*p_num_dma_dev = num_dma_dev;

@@ -1722,6 +1665,109 @@ static int cam_jpeg_mgr_hw_dump(void *hw_mgr_priv, void *dump_hw_args)
	return rc;
}

static void cam_jpeg_mgr_dump_pf_data(
	struct cam_jpeg_hw_mgr  *hw_mgr,
	struct cam_hw_cmd_args  *hw_cmd_args)
{
	struct cam_jpeg_hw_ctx_data    *ctx_data;
	struct cam_packet              *packet;
	struct cam_jpeg_match_pid_args  jpeg_pid_mid_args;
	struct cam_buf_io_cfg          *io_cfg = NULL;
	uint32_t                        dev_type;
	dma_addr_t   iova_addr;
	size_t       src_buf_size;
	int          i, j;
	int32_t    mmu_hdl;
	bool      hw_pid_support = true;
	int rc = 0;

	ctx_data = (struct cam_jpeg_hw_ctx_data  *)hw_cmd_args->ctxt_to_hw_map;
	packet  = hw_cmd_args->u.pf_args.pf_data.packet;

	jpeg_pid_mid_args.fault_mid = hw_cmd_args->u.pf_args.mid;
	jpeg_pid_mid_args.pid = hw_cmd_args->u.pf_args.pid;
	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;

	if (!hw_mgr->num_pid[dev_type]) {
		hw_pid_support = false;
		goto iodump;
	}

	rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
		hw_mgr->devices[dev_type][0]->hw_priv,
		CAM_JPEG_CMD_MATCH_PID_MID,
		&jpeg_pid_mid_args, sizeof(jpeg_pid_mid_args));
	if (rc) {
		CAM_ERR(CAM_JPEG, "CAM_JPEG_CMD_MATCH_PID_MID failed %d", rc);
		return;
	}

	if (!jpeg_pid_mid_args.pid_match_found) {
		CAM_INFO(CAM_JPEG, "This context data is not matched with pf pid and mid");
		return;
	}

iodump:
	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
		packet->io_configs_offset / 4);

	for (i = 0; i < packet->num_io_configs; i++) {
		if (hw_pid_support) {
			if (io_cfg[i].resource_type !=
				jpeg_pid_mid_args.match_res)
				continue;

			if (i == packet->num_io_configs) {
				CAM_ERR(CAM_JPEG,
					"getting io port for mid resource id failed  req id:%lld res id:0x%x",
					packet->header.request_id,
					jpeg_pid_mid_args.match_res);
				return;
			}
		}

		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
			if (!io_cfg[i].mem_handle[j])
				break;

			CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d",
				io_cfg[i].resource_type,
				io_cfg[i].fence,
				io_cfg[i].format,
				io_cfg[i].direction);

			mmu_hdl = cam_mem_is_secure_buf(
				io_cfg[i].mem_handle[j]) ? hw_mgr->iommu_sec_hdl :
				hw_mgr->iommu_hdl;
			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
				mmu_hdl, &iova_addr, &src_buf_size);
			if (rc < 0) {
				CAM_ERR(CAM_UTIL, "get src buf address fail");
				continue;
			}
			if ((iova_addr & 0xFFFFFFFF) != iova_addr) {
				CAM_ERR(CAM_JPEG, "Invalid mapped address");
				rc = -EINVAL;
				continue;
			}

			CAM_INFO(CAM_JPEG,
				"pln %u w %u h %u stride %u slice %u size %d addr 0x%x offset 0x%x memh %x",
				j, io_cfg[i].planes[j].width,
				io_cfg[i].planes[j].height,
				io_cfg[i].planes[j].plane_stride,
				io_cfg[i].planes[j].slice_height,
				(int32_t)src_buf_size,
				(unsigned int)iova_addr,
				io_cfg[i].offsets[j],
				io_cfg[i].mem_handle[j]);
		}

		if (hw_pid_support)
			return;
	}
}

static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
	int rc = 0;
@@ -1735,15 +1781,11 @@ static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args)

	switch (hw_cmd_args->cmd_type) {
	case CAM_HW_MGR_CMD_DUMP_PF_INFO:
		cam_jpeg_mgr_print_io_bufs(
			hw_cmd_args->u.pf_args.pf_data.packet,
			hw_mgr->iommu_hdl,
			hw_mgr->iommu_sec_hdl,
			hw_cmd_args->u.pf_args.buf_info,
			hw_cmd_args->u.pf_args.mem_found);
		cam_jpeg_mgr_dump_pf_data(hw_mgr, hw_cmd_args);
		break;
	default:
		CAM_ERR(CAM_JPEG, "Invalid cmd");
		CAM_ERR(CAM_JPEG, "Invalid cmd :%d",
			hw_cmd_args->cmd_type);
	}

	return rc;
+2 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ struct cam_jpeg_hw_ctx_data {
 * @hw_config_req_list: Pending hw update requests list
 * @free_req_list: Free nodes for above list
 * @req_list: Nodes of hw update list
 * @num_pid: num of pids supported in the device
 */
struct cam_jpeg_hw_mgr {
	struct mutex hw_mgr_mutex;
@@ -160,6 +161,7 @@ struct cam_jpeg_hw_mgr {
	struct list_head hw_config_req_list;
	struct list_head free_req_list;
	struct cam_jpeg_hw_cfg_req req_list[CAM_JPEG_HW_CFG_Q_MAX];
	uint32_t num_pid[CAM_JPEG_DEV_TYPE_MAX];
};

#endif /* CAM_JPEG_HW_MGR_H */
+11 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
 */

#ifndef CAM_JPEG_HW_INTF_H
@@ -17,6 +17,7 @@

#define CAM_JPEG_HW_DUMP_TAG_MAX_LEN 32
#define CAM_JPEG_HW_DUMP_NUM_WORDS   5
#define CAM_JPEG_HW_MAX_NUM_PID      2

enum cam_jpeg_hw_type {
	CAM_JPEG_DEV_ENC,
@@ -43,10 +44,19 @@ struct cam_jpeg_hw_dump_header {
	uint32_t    word_size;
};

struct cam_jpeg_match_pid_args {
	uint32_t    pid;
	uint32_t    fault_mid;
	bool        pid_match_found;
	uint32_t    match_res;
};

enum cam_jpeg_cmd_type {
	CAM_JPEG_CMD_CDM_CFG,
	CAM_JPEG_CMD_SET_IRQ_CB,
	CAM_JPEG_CMD_HW_DUMP,
	CAM_JPEG_CMD_GET_NUM_PID,
	CAM_JPEG_CMD_MATCH_PID_MID,
	CAM_JPEG_CMD_MAX,
};

+45 −2
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
 */

#include <linux/of.h>
@@ -377,7 +377,9 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
{
	struct cam_hw_info *jpeg_dma_dev = device_priv;
	struct cam_jpeg_dma_device_core_info *core_info = NULL;
	int rc;
	struct cam_jpeg_match_pid_args       *match_pid_mid = NULL;
	uint32_t    *num_pid = NULL;
	int i, rc = 0;

	if (!device_priv) {
		CAM_ERR(CAM_JPEG, "Invalid arguments");
@@ -412,6 +414,47 @@ int cam_jpeg_dma_process_cmd(void *device_priv, uint32_t cmd_type,
		rc = 0;
		break;
	}
	case CAM_JPEG_CMD_GET_NUM_PID:
		if (!cmd_args) {
			CAM_ERR(CAM_JPEG, "cmd args NULL");
			return -EINVAL;
		}

		num_pid = (uint32_t    *)cmd_args;
		*num_pid = core_info->num_pid;

		break;
	case CAM_JPEG_CMD_MATCH_PID_MID:
		match_pid_mid = (struct cam_jpeg_match_pid_args *)cmd_args;

		if (!cmd_args) {
			CAM_ERR(CAM_JPEG, "cmd args NULL");
			return -EINVAL;
		}

		for (i = 0; i < core_info->num_pid; i++) {
			if (core_info->pid[i] == match_pid_mid->pid)
				break;
		}

		if (i == core_info->num_pid)
			match_pid_mid->pid_match_found = false;
		else
			match_pid_mid->pid_match_found = true;

		if (match_pid_mid->pid_match_found) {
			if (match_pid_mid->fault_mid == core_info->rd_mid) {
				match_pid_mid->match_res =
					CAM_JPEG_DMA_INPUT_IMAGE;
			} else if (match_pid_mid->fault_mid ==
				core_info->wr_mid) {
				match_pid_mid->match_res =
					CAM_JPEG_DMA_OUTPUT_IMAGE;
			} else
				match_pid_mid->pid_match_found = false;
		}

		break;
	default:
		rc = -EINVAL;
		break;
+5 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
 */

#ifndef CAM_JPEG_DMA_CORE_H
@@ -63,6 +63,10 @@ struct cam_jpeg_dma_device_core_info {
	int32_t ref_count;
	struct mutex core_mutex;
	int32_t result_size;
	uint32_t num_pid;
	uint32_t pid[CAM_JPEG_HW_MAX_NUM_PID];
	uint32_t rd_mid;
	uint32_t wr_mid;
};

int cam_jpeg_dma_init_hw(void *device_priv,
Loading