msm: camera: icp: Add support for synx testing
Add support to receive synx test cmds, and forward it to ICP FW. Synx on ICP will process that cmd, and send a response. This response is returned to the caller. The objective of this infrastructure is to allow synx test app to validate synx functionality on ICP without running any actual use-case. CRs-Fixed: 3448052 Change-Id: I3785264f74c5c698146f4de1a82d25fe141cfc2a Signed-off-by: Karthik Anantha Ram <quic_kartanan@quicinc.com>
This commit is contained in:

committed by
Camera Software Integration

parent
c5af31b5fd
commit
9bf7e70f2d
@@ -651,6 +651,7 @@ struct cam_hw_inject_evt_param {
|
||||
* @hw_dump: Function pointer for HW dump
|
||||
* @hw_recovery: Function pointer for HW recovery callback
|
||||
* @hw_inject_evt: Function pointer for HW event injection callback
|
||||
* @synx_trigger: Function pointer for synx test trigger
|
||||
*
|
||||
*/
|
||||
struct cam_hw_mgr_intf {
|
||||
@@ -676,6 +677,7 @@ struct cam_hw_mgr_intf {
|
||||
int (*hw_dump)(void *hw_priv, void *hw_dump_args);
|
||||
int (*hw_recovery)(void *hw_priv, void *hw_recovery_args);
|
||||
void (*hw_inject_evt)(void *hw_priv, void *evt_args);
|
||||
int (*synx_trigger)(void *hw_priv, void *synx_params);
|
||||
};
|
||||
|
||||
#endif /* _CAM_HW_MGR_INTF_H_ */
|
||||
|
@@ -736,6 +736,26 @@ int cam_node_shutdown(struct cam_node *node)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cam_node_handle_synx_test(
|
||||
struct cam_node *node, void *params)
|
||||
{
|
||||
int i, rc = -EINVAL;
|
||||
|
||||
for (i = 0; i < node->ctx_size; i++) {
|
||||
if (node->ctx_list[i].dev_hdl > 0) {
|
||||
CAM_ERR(CAM_CORE, "Node [%s] has active context [%d]",
|
||||
node->name, i);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->hw_mgr_intf.synx_trigger)
|
||||
rc = node->hw_mgr_intf.synx_trigger(
|
||||
node->hw_mgr_intf.hw_mgr_priv, params);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_node_init(struct cam_node *node, struct cam_hw_mgr_intf *hw_mgr_intf,
|
||||
struct cam_context *ctx_list, uint32_t ctx_size, char *name)
|
||||
{
|
||||
@@ -1030,6 +1050,21 @@ release_kfree:
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CAM_SYNX_TEST_TRIGGER: {
|
||||
struct cam_synx_test_params synx_params;
|
||||
|
||||
if (copy_from_user(&synx_params, u64_to_user_ptr(cmd->handle),
|
||||
sizeof(synx_params))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = __cam_node_handle_synx_test(node, &synx_params);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_CORE, "Synx test on %s failed(rc = %d)",
|
||||
node->name, rc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CAM_ERR(CAM_CORE, "Unknown op code %d", cmd->op_code);
|
||||
rc = -EINVAL;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_HFI_SESSION_DEFS_H
|
||||
@@ -595,4 +595,23 @@ struct hfi_msg_ipe_frame_process {
|
||||
uint64_t user_data;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct hfi_cmd_synx_test_payload
|
||||
* Same struct used for cmd and response
|
||||
*
|
||||
* @size: Size of the pkt
|
||||
* @pkt_type: pkt type (cmd/response)
|
||||
* @input_size: Input buffer size
|
||||
* @input_iova: Input buffer address
|
||||
* @output_size: Output buffer size
|
||||
* @output_iova: Output buffer address
|
||||
*/
|
||||
struct hfi_cmd_synx_test_payload {
|
||||
uint32_t size;
|
||||
uint32_t pkt_type;
|
||||
uint32_t input_size;
|
||||
uint32_t input_iova;
|
||||
uint32_t output_size;
|
||||
uint32_t output_iova;
|
||||
} __packed;
|
||||
#endif /* _CAM_HFI_SESSION_DEFS_H */
|
||||
|
@@ -122,6 +122,7 @@
|
||||
#define HFI_CMD_DBG_COMMON_START \
|
||||
(HFI_DOMAIN_BASE_DBG + HFI_CMD_START_OFFSET + 0x0)
|
||||
#define HFI_CMD_DBG_TEST_START (HFI_CMD_DBG_COMMON_START + 0x800)
|
||||
#define HFI_CMD_DBG_SYNX_TEST (HFI_CMD_DBG_TEST_START + 0x1)
|
||||
#define HFI_CMD_DBG_END (HFI_CMD_DBG_COMMON_START + 0xFFF)
|
||||
|
||||
/* System level messages */
|
||||
@@ -192,8 +193,10 @@
|
||||
|
||||
/* ICP core level Debug test message range */
|
||||
#define HFI_MSG_DBG_COMMON_START \
|
||||
(HFI_DOMAIN_BASE_DBG + 0x0)
|
||||
(HFI_DOMAIN_BASE_DBG + HFI_MSG_START_OFFSET + 0x0)
|
||||
|
||||
#define HFI_MSG_DBG_TEST_START (HFI_MSG_DBG_COMMON_START + 0x800)
|
||||
#define HFI_MSG_DBG_SYNX_TEST (HFI_MSG_DBG_TEST_START + 0x1)
|
||||
#define HFI_MSG_DBG_END (HFI_MSG_DBG_COMMON_START + 0xFFF)
|
||||
|
||||
/* System level property base offset */
|
||||
|
@@ -3070,6 +3070,11 @@ static int cam_icp_process_msg_pkt_type(
|
||||
|
||||
break;
|
||||
|
||||
case HFI_MSG_DBG_SYNX_TEST:
|
||||
CAM_DBG(CAM_ICP, "received DBG_SYNX_TEST");
|
||||
size_processed = sizeof(struct hfi_cmd_synx_test_payload);
|
||||
complete(&hw_mgr->icp_complete);
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ICP, "[%s] invalid msg : %u",
|
||||
hw_mgr->hw_mgr_name, msg_ptr[ICP_PACKET_TYPE]);
|
||||
@@ -3969,7 +3974,6 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr)
|
||||
bool send_freq_info = true;
|
||||
|
||||
CAM_DBG(CAM_PERF, "[%s] ENTER", hw_mgr->hw_mgr_name);
|
||||
|
||||
if (!icp_dev_intf) {
|
||||
CAM_ERR(CAM_ICP, "[%s] ICP device interface is NULL", hw_mgr->hw_mgr_name);
|
||||
return -EINVAL;
|
||||
@@ -6600,6 +6604,137 @@ static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_synx_core_control(
|
||||
struct cam_icp_hw_mgr *hw_mgr,
|
||||
struct cam_synx_core_control *synx_core_ctrl)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (synx_core_ctrl->core_control) {
|
||||
rc = cam_icp_mgr_icp_resume(hw_mgr);
|
||||
if (!rc)
|
||||
/* Set FW log level for synx */
|
||||
if (hw_mgr->icp_debug_type)
|
||||
hfi_set_debug_level(hw_mgr->hfi_handle,
|
||||
hw_mgr->icp_debug_type, hw_mgr->icp_dbg_lvl);
|
||||
} else {
|
||||
rc = cam_icp_mgr_icp_power_collapse(hw_mgr);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ICP, "[%s] Failed to process core control resume: %s",
|
||||
hw_mgr->hw_mgr_name, CAM_BOOL_TO_YESNO(synx_core_ctrl->core_control));
|
||||
|
||||
CAM_INFO(CAM_ICP, "Synx test core control: %s done rc: %d",
|
||||
CAM_BOOL_TO_YESNO(synx_core_ctrl->core_control), rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_synx_send_test_cmd(
|
||||
struct cam_icp_hw_mgr *hw_mgr,
|
||||
struct cam_synx_test_cmd *synx_test_params)
|
||||
{
|
||||
int rc = 0;
|
||||
size_t size;
|
||||
dma_addr_t iova;
|
||||
struct hfi_cmd_synx_test_payload synx_test_cmd;
|
||||
unsigned long rem_jiffies;
|
||||
int timeout = 5000;
|
||||
|
||||
if (!hw_mgr->icp_resumed) {
|
||||
rc = cam_icp_mgr_icp_resume(hw_mgr);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ICP, "Failed to resume ICP rc: %d", rc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Set FW log level for synx */
|
||||
if (hw_mgr->icp_debug_type)
|
||||
hfi_set_debug_level(hw_mgr->hfi_handle,
|
||||
hw_mgr->icp_debug_type, hw_mgr->icp_dbg_lvl);
|
||||
}
|
||||
|
||||
synx_test_cmd.pkt_type = HFI_CMD_DBG_SYNX_TEST;
|
||||
synx_test_cmd.size = sizeof(synx_test_cmd);
|
||||
|
||||
rc = cam_mem_get_io_buf(synx_test_params->ip_mem_hdl, hw_mgr->iommu_hdl,
|
||||
&iova, &size, NULL);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ICP, "Failed to get buf for hdl: %d rc: %d",
|
||||
synx_test_params->ip_mem_hdl, rc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
synx_test_cmd.input_iova = (uint32_t)iova;
|
||||
synx_test_cmd.input_size = (uint32_t)size;
|
||||
|
||||
rc = cam_mem_get_io_buf(synx_test_params->op_mem_hdl, hw_mgr->iommu_hdl,
|
||||
&iova, &size, NULL);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ICP, "Failed to get buf for hdl: %d rc: %d",
|
||||
synx_test_params->ip_mem_hdl, rc);
|
||||
goto end;
|
||||
}
|
||||
|
||||
synx_test_cmd.output_iova = (uint32_t)iova;
|
||||
synx_test_cmd.output_size = (uint32_t)size;
|
||||
|
||||
CAM_DBG(CAM_ICP,
|
||||
"Input (hdl: 0x%x iova: 0x%x size: 0x%x) output (hdl: 0x%x iova: 0x%x size: 0x%x)",
|
||||
synx_test_params->ip_mem_hdl, synx_test_cmd.input_iova, synx_test_cmd.input_size,
|
||||
synx_test_params->op_mem_hdl, synx_test_cmd.output_iova, synx_test_cmd.output_size);
|
||||
|
||||
reinit_completion(&hw_mgr->icp_complete);
|
||||
rc = hfi_write_cmd(hw_mgr->hfi_handle, &synx_test_cmd);
|
||||
if (rc)
|
||||
goto end;
|
||||
|
||||
rem_jiffies = CAM_COMMON_WAIT_FOR_COMPLETION_TIMEOUT_ERRMSG(
|
||||
&hw_mgr->icp_complete, msecs_to_jiffies(timeout), CAM_ICP,
|
||||
"FW response timeout for synx test cmd");
|
||||
if (!rem_jiffies) {
|
||||
rc = -ETIMEDOUT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
CAM_INFO(CAM_ICP, "Synx test cmd done rc: %d", rc);
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_service_synx_test_cmds(void *hw_priv, void *synx_args)
|
||||
{
|
||||
int rc;
|
||||
struct cam_icp_hw_mgr *hw_mgr = hw_priv;
|
||||
struct cam_synx_test_params *synx_params;
|
||||
|
||||
if ((!hw_priv) || (!synx_args)) {
|
||||
CAM_ERR(CAM_ICP, "Input params are Null:");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
synx_params = (struct cam_synx_test_params *)synx_args;
|
||||
mutex_lock(&hw_mgr->hw_mgr_mutex);
|
||||
switch (synx_params->cmd_type) {
|
||||
case CAM_SYNX_TEST_CMD_TYPE_CORE_CTRL: {
|
||||
rc = cam_icp_mgr_synx_core_control(hw_mgr, &synx_params->u.core_ctrl);
|
||||
}
|
||||
break;
|
||||
case CAM_SYNX_TEST_CMD_TYPE_SYNX_CMD: {
|
||||
rc = cam_icp_mgr_synx_send_test_cmd(hw_mgr, &synx_params->u.test_cmd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args)
|
||||
{
|
||||
struct cam_hw_flush_args *flush_args = hw_flush_args;
|
||||
@@ -8007,6 +8142,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
hw_mgr_intf->hw_inject_evt = cam_icp_mgr_inject_evt;
|
||||
hw_mgr->secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
hw_mgr->mini_dump_cb = mini_dump_cb;
|
||||
hw_mgr_intf->synx_trigger = cam_icp_mgr_service_synx_test_cmds;
|
||||
|
||||
mutex_init(&hw_mgr->hw_mgr_mutex);
|
||||
spin_lock_init(&hw_mgr->hw_mgr_lock);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __UAPI_CAM_DEFS_H__
|
||||
@@ -30,6 +30,7 @@
|
||||
#define CAM_RELEASE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x2)
|
||||
#define CAM_DUMP_REQ (CAM_COMMON_OPCODE_BASE_v2 + 0x3)
|
||||
#define CAM_QUERY_CAP_V3 (CAM_COMMON_OPCODE_BASE_v2 + 0x4)
|
||||
#define CAM_SYNX_TEST_TRIGGER (CAM_COMMON_OPCODE_BASE_v2 + 0x5)
|
||||
|
||||
#define CAM_EXT_OPCODE_BASE 0x200
|
||||
#define CAM_CONFIG_DEV_EXTERNAL (CAM_EXT_OPCODE_BASE + 0x1)
|
||||
@@ -258,6 +259,10 @@ struct cam_iommu_handle {
|
||||
/* constants */
|
||||
#define CAM_PACKET_MAX_PLANES 3
|
||||
|
||||
/* synx test cmd types */
|
||||
#define CAM_SYNX_TEST_CMD_TYPE_CORE_CTRL 1
|
||||
#define CAM_SYNX_TEST_CMD_TYPE_SYNX_CMD 2
|
||||
|
||||
/**
|
||||
* struct cam_plane_cfg - Plane configuration info
|
||||
*
|
||||
@@ -907,4 +912,73 @@ struct cam_dump_req_cmd {
|
||||
__s32 dev_handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_synx_test_cmd - Synx test cmds
|
||||
*
|
||||
* @version: Struct version
|
||||
* @ip_mem_hdl: Input buf mem handle
|
||||
* corresponds to synx test inputs to the
|
||||
* fencing core
|
||||
* @op_mem_hdl: Output buf mem handle
|
||||
* corresponds to synx output generated by
|
||||
* the fencing core
|
||||
* @num_valid_params: Num valid params
|
||||
* @valid_param_mask: Valid param mask
|
||||
* @params: additional params
|
||||
*/
|
||||
struct cam_synx_test_cmd {
|
||||
__u32 version;
|
||||
__s32 ip_mem_hdl;
|
||||
__s32 op_mem_hdl;
|
||||
__u32 num_valid_params;
|
||||
__u32 valid_param_mask;
|
||||
__u32 params[5];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_synx_core_control - Synx core ctrl
|
||||
*
|
||||
* @version: Struct version
|
||||
* @core_control: Set for resume, unset for collapse
|
||||
* @num_valid_params: Num valid params
|
||||
* @valid_param_mask: Valid param mask
|
||||
* @params: additional params
|
||||
*/
|
||||
struct cam_synx_core_control {
|
||||
__u32 version;
|
||||
__u32 core_control;
|
||||
__u32 num_valid_params;
|
||||
__u32 valid_param_mask;
|
||||
__u32 params[4];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct cam_synx_test_params - Synx test params
|
||||
*
|
||||
* A test sequence could include creating and signaling
|
||||
* synx handle between ICP <-> APPs. These test params
|
||||
* would be cmds such as session initialize, synx create,
|
||||
* synx async wait, synx signal and so on
|
||||
*
|
||||
* @version: Struct version
|
||||
* @cmd_type: Type of test cmd - core control/synx cmd/...
|
||||
* @num_valid_params: Num valid params
|
||||
* @valid_param_mask: Valid param mask
|
||||
* @params: additional params
|
||||
* @test_cmd: Synx test cmd forwarded to the core
|
||||
* @core_ctrl: Synx test cmd to control fencing core
|
||||
*/
|
||||
struct cam_synx_test_params {
|
||||
__u32 version;
|
||||
__u32 cmd_type;
|
||||
__u32 num_valid_params;
|
||||
__u32 valid_param_mask;
|
||||
__u32 params[4];
|
||||
union {
|
||||
struct cam_synx_test_cmd test_cmd;
|
||||
struct cam_synx_core_control core_ctrl;
|
||||
} u;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#endif /* __UAPI_CAM_DEFS_H__ */
|
||||
|
Reference in New Issue
Block a user