msm: camera: common: Add camera error injection utility
Add and implement sysfs parameters to inject errors to camera HW on demand through UMD for IFE,ICP and JPEG. CRs-Fixed: 3115857 Change-Id: I4376fe31016cd81ad7e6f04cbc55e8ce010a6154 Signed-off-by: Pranav Sanwal <quic_psanwal@quicinc.com>
This commit is contained in:

committed by
Camera Software Integration

vanhempi
b997a29613
commit
1220255b08
@@ -769,3 +769,31 @@ void cam_context_getref(struct cam_context *ctx)
|
||||
ctx->dev_hdl, refcount_read(&(ctx->refcount.refcount)),
|
||||
ctx->dev_name);
|
||||
}
|
||||
|
||||
int cam_context_add_err_inject(struct cam_context *ctx, void *err_param)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!ctx->state_machine) {
|
||||
CAM_ERR(CAM_CORE, "Context is not ready");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&ctx->ctx_mutex);
|
||||
if ((ctx->state > CAM_CTX_AVAILABLE) &&
|
||||
(ctx->state < CAM_CTX_STATE_MAX)) {
|
||||
if (ctx->state_machine[ctx->state].err_inject_ops) {
|
||||
rc = ctx->state_machine[ctx->state].err_inject_ops(
|
||||
ctx, err_param);
|
||||
} else {
|
||||
CAM_WARN(CAM_CORE, "No err inject ops in dev %d,state %d",
|
||||
ctx->dev_hdl, ctx->state);
|
||||
}
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->ctx_mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "cam_req_mgr_interface.h"
|
||||
#include "cam_hw_mgr_intf.h"
|
||||
#include "cam_smmu_api.h"
|
||||
#include "cam_common_util.h"
|
||||
|
||||
/* Forward declarations */
|
||||
struct cam_context;
|
||||
@@ -164,6 +165,7 @@ struct cam_ctx_crm_ops {
|
||||
* context info
|
||||
* @recovery_ops: Function to be invoked to try hardware recovery
|
||||
* @mini_dump_ops: Function for mini dump
|
||||
* @err_inject_ops: Function for error injection
|
||||
*
|
||||
*/
|
||||
struct cam_ctx_ops {
|
||||
@@ -174,8 +176,10 @@ struct cam_ctx_ops {
|
||||
cam_ctx_info_dump_cb_func dumpinfo_ops;
|
||||
cam_ctx_recovery_cb_func recovery_ops;
|
||||
cam_ctx_mini_dump_cb_func mini_dump_ops;
|
||||
cam_ctx_err_inject_cb_func err_inject_ops;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct cam_context - camera context object for the subdevice node
|
||||
*
|
||||
@@ -596,4 +600,17 @@ void cam_context_putref(struct cam_context *ctx);
|
||||
*/
|
||||
void cam_context_getref(struct cam_context *ctx);
|
||||
|
||||
/**
|
||||
* cam_context_add_err_inject()
|
||||
*
|
||||
* @brief: Add error inject parameters through err_inject_ops.
|
||||
*
|
||||
* @ctx: Context for which error is to be injected
|
||||
*
|
||||
* @err_param: Error injection parameters
|
||||
*
|
||||
*/
|
||||
int cam_context_add_err_inject(struct cam_context *ctx,
|
||||
void *err_param);
|
||||
|
||||
#endif /* _CAM_CONTEXT_H_ */
|
||||
|
@@ -1575,6 +1575,26 @@ end:
|
||||
*bytes_updated = bytes_written;
|
||||
}
|
||||
|
||||
int cam_context_err_to_hw(struct cam_context *ctx, void *args)
|
||||
{
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (!ctx || !args) {
|
||||
CAM_ERR(CAM_CTXT, "invalid params for error injection");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ctx->hw_mgr_intf->hw_inject_err) {
|
||||
ctx->hw_mgr_intf->hw_inject_err(ctx->ctxt_to_hw_map, args);
|
||||
rc = 0;
|
||||
} else {
|
||||
CAM_ERR(CAM_CTXT, "hw_intf cb absent for dev hdl: %lld, ctx id: %lld",
|
||||
ctx->dev_hdl, ctx->ctx_id);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_context_mini_dump(struct cam_context *ctx, void *args)
|
||||
{
|
||||
struct cam_hw_mini_dump_info *md;
|
||||
|
@@ -37,4 +37,5 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
|
||||
size_t cam_context_parse_config_cmd(struct cam_context *ctx, struct cam_config_dev_cmd *cmd,
|
||||
struct cam_packet **packet);
|
||||
int cam_context_mini_dump(struct cam_context *ctx, void *args);
|
||||
int cam_context_err_to_hw(struct cam_context *ctx, void *args);
|
||||
#endif /* _CAM_CONTEXT_UTILS_H_ */
|
||||
|
@@ -65,6 +65,10 @@ typedef int (*cam_ctx_recovery_cb_func)(void *context,
|
||||
typedef int (*cam_ctx_mini_dump_cb_func)(void *context,
|
||||
void *args);
|
||||
|
||||
/* ctx error inject callback function type */
|
||||
typedef int (*cam_ctx_err_inject_cb_func)(void *context,
|
||||
void *args);
|
||||
|
||||
/**
|
||||
* struct cam_hw_update_entry - Entry for hardware config
|
||||
*
|
||||
@@ -496,6 +500,21 @@ struct cam_hw_mini_dump_info {
|
||||
uint8_t hw_mgr_ctx_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_hw_err_param - cam hHW error injection parameters
|
||||
*
|
||||
* @err_type error type for the injected error
|
||||
* @err_code error code for the injected error
|
||||
* @err_req_id Req Id for which the error is injected
|
||||
* @is_valid bool flag to indicate if error injection is enabled for a context
|
||||
*/
|
||||
struct cam_hw_err_param {
|
||||
uint32_t err_type;
|
||||
uint32_t err_code;
|
||||
uint64_t err_req_id;
|
||||
bool is_valid;
|
||||
};
|
||||
|
||||
/**
|
||||
* cam_hw_mgr_intf - HW manager interface
|
||||
*
|
||||
@@ -526,6 +545,7 @@ struct cam_hw_mini_dump_info {
|
||||
* @hw_reset: Function pointer for HW reset
|
||||
* @hw_dump: Function pointer for HW dump
|
||||
* @hw_recovery: Function pointer for HW recovery callback
|
||||
* @hw_inject_err Function pointer for HW error injection callback
|
||||
*
|
||||
*/
|
||||
struct cam_hw_mgr_intf {
|
||||
@@ -549,6 +569,7 @@ struct cam_hw_mgr_intf {
|
||||
int (*hw_reset)(void *hw_priv, void *hw_reset_args);
|
||||
int (*hw_dump)(void *hw_priv, void *hw_dump_args);
|
||||
int (*hw_recovery)(void *hw_priv, void *hw_recovery_args);
|
||||
void (*hw_inject_err)(void *hw_priv, void *hw_err_inject_args);
|
||||
};
|
||||
|
||||
#endif /* _CAM_HW_MGR_INTF_H_ */
|
||||
|
@@ -111,6 +111,8 @@ static int __cam_icp_release_dev_in_acquired(struct cam_context *ctx,
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ICP, "Unable to release device");
|
||||
|
||||
cam_common_release_err_params(ctx->dev_hdl);
|
||||
|
||||
ctx->state = CAM_CTX_AVAILABLE;
|
||||
trace_cam_context_state("ICP", ctx);
|
||||
return rc;
|
||||
@@ -326,6 +328,48 @@ static int __cam_icp_ctx_handle_hw_event(void *ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_icp_context_inject_error(void *context, void *err_param)
|
||||
{
|
||||
int rc = 0;
|
||||
uint32_t err_code;
|
||||
uint32_t err_type;
|
||||
uint64_t req_id;
|
||||
struct cam_context *ctx = (struct cam_context *)context;
|
||||
|
||||
if (!err_param) {
|
||||
CAM_ERR(CAM_ICP, "err_params is not valid");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err_code = ((struct cam_err_inject_param *)err_param)->err_code;
|
||||
err_type = ((struct cam_err_inject_param *)err_param)->err_type;
|
||||
req_id = ((struct cam_err_inject_param *)err_param)->req_id;
|
||||
|
||||
switch (err_type) {
|
||||
case CAM_SYNC_STATE_SIGNALED_ERROR:
|
||||
switch (err_code) {
|
||||
case CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE:
|
||||
case CAM_SYNC_ICP_EVENT_CONFIG_ERR:
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ICP, "ICP Error code %d not supported!", err_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ICP, "ICP Error type: %d not supported!", err_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CAM_INFO(CAM_ICP,
|
||||
"Err inject params: err_code: %u err_type: %u, to dev_hdl: %lld",
|
||||
err_code, err_type, ctx->dev_hdl);
|
||||
|
||||
rc = cam_context_err_to_hw(ctx, err_param);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct cam_ctx_ops
|
||||
cam_icp_ctx_state_machine[CAM_CTX_STATE_MAX] = {
|
||||
/* Uninit */
|
||||
@@ -356,6 +400,7 @@ static struct cam_ctx_ops
|
||||
.irq_ops = __cam_icp_ctx_handle_hw_event,
|
||||
.pagefault_ops = cam_icp_context_dump_active_request,
|
||||
.mini_dump_ops = cam_icp_context_mini_dump,
|
||||
.err_inject_ops = cam_icp_context_inject_error,
|
||||
},
|
||||
/* Ready */
|
||||
{
|
||||
@@ -370,6 +415,7 @@ static struct cam_ctx_ops
|
||||
.irq_ops = __cam_icp_ctx_handle_hw_event,
|
||||
.pagefault_ops = cam_icp_context_dump_active_request,
|
||||
.mini_dump_ops = cam_icp_context_mini_dump,
|
||||
.err_inject_ops = cam_icp_context_inject_error,
|
||||
},
|
||||
/* Flushed */
|
||||
{
|
||||
@@ -382,6 +428,7 @@ static struct cam_ctx_ops
|
||||
.irq_ops = NULL,
|
||||
.pagefault_ops = cam_icp_context_dump_active_request,
|
||||
.mini_dump_ops = cam_icp_context_mini_dump,
|
||||
.err_inject_ops = cam_icp_context_inject_error,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_smmu_api.h"
|
||||
#include "camera_main.h"
|
||||
#include "cam_common_util.h"
|
||||
|
||||
#define CAM_ICP_DEV_NAME "cam-icp"
|
||||
|
||||
@@ -50,6 +51,23 @@ static const struct of_device_id cam_icp_dt_match[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static int cam_icp_dev_err_inject_cb(void *err_param)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
|
||||
if (g_icp_dev.ctx[i].dev_hdl ==
|
||||
((struct cam_err_inject_param *)err_param)->dev_hdl) {
|
||||
CAM_INFO(CAM_ICP, "ICP err inject dev_hdl found:%d",
|
||||
g_icp_dev.ctx[i].dev_hdl);
|
||||
cam_context_add_err_inject(&g_icp_dev.ctx[i], err_param);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
CAM_ERR(CAM_ICP, "No dev hdl found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void cam_icp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -223,6 +241,9 @@ static int cam_icp_component_bind(struct device *dev,
|
||||
goto ctx_fail;
|
||||
}
|
||||
|
||||
cam_common_register_err_inject_cb(cam_icp_dev_err_inject_cb,
|
||||
CAM_COMMON_ERR_INJECT_HW_ICP);
|
||||
|
||||
node->sd_handler = cam_icp_subdev_close_internal;
|
||||
cam_smmu_set_client_page_fault_handler(iommu_hdl,
|
||||
cam_icp_dev_iommu_fault_handler, node);
|
||||
|
@@ -2248,6 +2248,33 @@ static const char *cam_icp_error_handle_id_to_type(
|
||||
return name;
|
||||
}
|
||||
|
||||
static inline void cam_icp_mgr_validate_inject_err(uint64_t current_req_id, uint32_t *event_id,
|
||||
struct cam_hw_done_event_data *buf_data, struct cam_icp_hw_ctx_data *ctx_data)
|
||||
{
|
||||
if (ctx_data->err_inject_params.err_req_id == current_req_id) {
|
||||
switch (ctx_data->err_inject_params.err_code) {
|
||||
case CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE:
|
||||
*event_id = CAM_CTX_EVT_ID_ERROR;
|
||||
buf_data->evt_param = CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE;
|
||||
break;
|
||||
case CAM_SYNC_ICP_EVENT_CONFIG_ERR:
|
||||
*event_id = CAM_CTX_EVT_ID_ERROR;
|
||||
buf_data->evt_param = CAM_SYNC_ICP_EVENT_CONFIG_ERR;
|
||||
break;
|
||||
default:
|
||||
CAM_INFO(CAM_ICP, "ICP error code not supported: %d",
|
||||
ctx_data->err_inject_params.err_code);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
return;
|
||||
|
||||
CAM_INFO(CAM_ICP, "ICP Err Induced! err_code: %u, req_id: %llu",
|
||||
ctx_data->err_inject_params.err_code, current_req_id);
|
||||
|
||||
memset(&(ctx_data->err_inject_params), 0, sizeof(struct cam_hw_err_param));
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
|
||||
{
|
||||
int i;
|
||||
@@ -2347,6 +2374,9 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
|
||||
"[%s]: BufDone Req %llu event_id %d",
|
||||
ctx_data->ctx_id_string, hfi_frame_process->request_id[idx], event_id);
|
||||
|
||||
if (ctx_data->err_inject_params.is_valid)
|
||||
cam_icp_mgr_validate_inject_err(request_id, &event_id, &buf_data, ctx_data);
|
||||
|
||||
buf_data.request_id = hfi_frame_process->request_id[idx];
|
||||
icp_done_evt.evt_id = event_id;
|
||||
icp_done_evt.buf_done_data = &buf_data;
|
||||
@@ -3914,6 +3944,8 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id)
|
||||
}
|
||||
|
||||
mutex_lock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
|
||||
memset(&(hw_mgr->ctx_data[ctx_id].err_inject_params), 0,
|
||||
sizeof(struct cam_hw_err_param));
|
||||
cam_icp_remove_ctx_bw(hw_mgr, &hw_mgr->ctx_data[ctx_id]);
|
||||
if (hw_mgr->ctx_data[ctx_id].state !=
|
||||
CAM_ICP_CTX_STATE_ACQUIRED) {
|
||||
@@ -6926,6 +6958,19 @@ static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cam_icp_mgr_inject_err(void *hw_mgr_priv, void *hw_err_inject_args)
|
||||
{
|
||||
struct cam_icp_hw_ctx_data *ctx_data = hw_mgr_priv;
|
||||
|
||||
ctx_data->err_inject_params.err_code = ((struct cam_err_inject_param *)
|
||||
hw_err_inject_args)->err_code;
|
||||
ctx_data->err_inject_params.err_type = ((struct cam_err_inject_param *)
|
||||
hw_err_inject_args)->err_type;
|
||||
ctx_data->err_inject_params.err_req_id = ((struct cam_err_inject_param *)
|
||||
hw_err_inject_args)->req_id;
|
||||
ctx_data->err_inject_params.is_valid = true;
|
||||
}
|
||||
|
||||
int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
int *iommu_hdl, cam_icp_mini_dump_cb mini_dump_cb)
|
||||
{
|
||||
@@ -6955,6 +7000,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush;
|
||||
hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd;
|
||||
hw_mgr_intf->hw_dump = cam_icp_mgr_hw_dump;
|
||||
hw_mgr_intf->hw_inject_err = cam_icp_mgr_inject_err;
|
||||
|
||||
icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
icp_hw_mgr.mini_dump_cb = mini_dump_cb;
|
||||
|
@@ -271,6 +271,7 @@ struct cam_ctx_clk_info {
|
||||
* @watch_dog_reset_counter: Counter for watch dog reset
|
||||
* @icp_dev_io_info: io config resource
|
||||
* @last_flush_req: last flush req for this ctx
|
||||
* @err_inject_params: Error injection data for hw_mgr_ctx
|
||||
* @abort_timed_out: Indicates if abort timed out
|
||||
*/
|
||||
struct cam_icp_hw_ctx_data {
|
||||
@@ -295,6 +296,7 @@ struct cam_icp_hw_ctx_data {
|
||||
struct cam_icp_acquire_dev_info icp_dev_io_info;
|
||||
uint64_t last_flush_req;
|
||||
char ctx_id_string[128];
|
||||
struct cam_hw_err_param err_inject_params;
|
||||
bool abort_timed_out;
|
||||
};
|
||||
|
||||
|
@@ -4009,6 +4009,24 @@ static struct cam_isp_ctx_irq_ops
|
||||
},
|
||||
};
|
||||
|
||||
static inline int cam_isp_context_apply_error(struct cam_hw_err_param *err_params,
|
||||
uint64_t current_req_id, struct cam_context *ctx)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (err_params->err_req_id == current_req_id) {
|
||||
CAM_INFO(CAM_ISP,
|
||||
"Err inject for req: %llu, err_code: %d, err_type: %d ctx id: %d",
|
||||
current_req_id, err_params->err_code, err_params->err_type, ctx->ctx_id);
|
||||
|
||||
__cam_isp_ctx_notify_v4l2_error_event(err_params->err_type, err_params->err_code,
|
||||
current_req_id, ctx);
|
||||
memset(err_params, 0, sizeof(struct cam_hw_err_param));
|
||||
return rc;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int __cam_isp_ctx_apply_req_in_activated_state(
|
||||
struct cam_context *ctx, struct cam_req_mgr_apply_request *apply,
|
||||
enum cam_isp_ctx_activated_substate next_state)
|
||||
@@ -4119,6 +4137,13 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
|
||||
cfg.reapply_type = req_isp->reapply_type;
|
||||
cfg.cdm_reset_before_apply = req_isp->cdm_reset_before_apply;
|
||||
|
||||
if (ctx_isp->err_inject_params.is_valid) {
|
||||
rc = cam_isp_context_apply_error(&(ctx_isp->err_inject_params),
|
||||
req->request_id, ctx_isp->base);
|
||||
if (!rc)
|
||||
goto end;
|
||||
}
|
||||
|
||||
atomic_set(&ctx_isp->apply_in_progress, 1);
|
||||
|
||||
rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
|
||||
@@ -5626,6 +5651,9 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
|
||||
ctx_isp->hw_ctx = NULL;
|
||||
}
|
||||
|
||||
cam_common_release_err_params(ctx->dev_hdl);
|
||||
memset(&(ctx_isp->err_inject_params), 0, sizeof(struct cam_hw_err_param));
|
||||
|
||||
ctx->session_hdl = -1;
|
||||
ctx->dev_hdl = -1;
|
||||
ctx->link_hdl = -1;
|
||||
@@ -7327,6 +7355,69 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_isp_context_inject_error(void *context, void *err_param)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_context *ctx = (struct cam_context *)context;
|
||||
struct cam_isp_context *ctx_isp = ctx->ctx_priv;
|
||||
uint64_t req_id;
|
||||
uint32_t err_code;
|
||||
uint32_t err_type;
|
||||
|
||||
if (!err_param) {
|
||||
CAM_ERR(CAM_ISP, "err_param not valid");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req_id = ((struct cam_err_inject_param *)err_param)->req_id;
|
||||
err_type = ((struct cam_err_inject_param *)err_param)->err_type;
|
||||
err_code = ((struct cam_err_inject_param *)err_param)->err_code;
|
||||
|
||||
switch (err_type) {
|
||||
case CAM_REQ_MGR_ERROR_TYPE_RECOVERY:
|
||||
switch (err_code) {
|
||||
case CAM_REQ_MGR_LINK_STALLED_ERROR:
|
||||
case CAM_REQ_MGR_CSID_FIFO_OVERFLOW_ERROR:
|
||||
case CAM_REQ_MGR_CSID_RECOVERY_OVERFLOW_ERROR:
|
||||
case CAM_REQ_MGR_CSID_PIXEL_COUNT_MISMATCH:
|
||||
case CAM_REQ_MGR_CSID_ERR_ON_SENSOR_SWITCHING:
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY:
|
||||
switch (err_code) {
|
||||
case CAM_REQ_MGR_CSID_FATAL_ERROR:
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE:
|
||||
err_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR;
|
||||
break;
|
||||
case CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT:
|
||||
err_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR;
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "err type not supported %d", err_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_ISP, "inject err isp code: %d type: %d ctx id: %d",
|
||||
err_code, err_type, ctx->ctx_id);
|
||||
|
||||
ctx_isp->err_inject_params.err_code = err_code;
|
||||
ctx_isp->err_inject_params.err_type = err_type;
|
||||
ctx_isp->err_inject_params.err_req_id = req_id;
|
||||
ctx_isp->err_inject_params.is_valid = true;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* top state machine */
|
||||
static struct cam_ctx_ops
|
||||
cam_isp_ctx_top_state_machine[CAM_CTX_STATE_MAX] = {
|
||||
@@ -7363,6 +7454,7 @@ static struct cam_ctx_ops
|
||||
.irq_ops = NULL,
|
||||
.pagefault_ops = cam_isp_context_dump_requests,
|
||||
.dumpinfo_ops = cam_isp_context_info_dump,
|
||||
.err_inject_ops = cam_isp_context_inject_error,
|
||||
},
|
||||
/* Ready */
|
||||
{
|
||||
@@ -7381,6 +7473,7 @@ static struct cam_ctx_ops
|
||||
.irq_ops = NULL,
|
||||
.pagefault_ops = cam_isp_context_dump_requests,
|
||||
.dumpinfo_ops = cam_isp_context_info_dump,
|
||||
.err_inject_ops = cam_isp_context_inject_error,
|
||||
},
|
||||
/* Flushed */
|
||||
{
|
||||
@@ -7398,6 +7491,7 @@ static struct cam_ctx_ops
|
||||
.irq_ops = NULL,
|
||||
.pagefault_ops = cam_isp_context_dump_requests,
|
||||
.dumpinfo_ops = cam_isp_context_info_dump,
|
||||
.err_inject_ops = cam_isp_context_inject_error,
|
||||
},
|
||||
/* Activated */
|
||||
{
|
||||
@@ -7421,6 +7515,7 @@ static struct cam_ctx_ops
|
||||
.pagefault_ops = cam_isp_context_dump_requests,
|
||||
.dumpinfo_ops = cam_isp_context_info_dump,
|
||||
.recovery_ops = cam_isp_context_hw_recovery,
|
||||
.err_inject_ops = cam_isp_context_inject_error,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -340,6 +340,7 @@ struct cam_isp_context {
|
||||
int32_t trigger_id;
|
||||
int64_t last_bufdone_err_apply_req_id;
|
||||
uint32_t v4l2_event_sub_ids;
|
||||
struct cam_hw_err_param err_inject_params;
|
||||
bool aeb_enabled;
|
||||
bool do_internal_recovery;
|
||||
};
|
||||
|
@@ -19,9 +19,25 @@
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_smmu_api.h"
|
||||
#include "camera_main.h"
|
||||
#include "cam_common_util.h"
|
||||
|
||||
static struct cam_isp_dev g_isp_dev;
|
||||
|
||||
static int cam_isp_dev_err_inject_cb(void *err_param)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < g_isp_dev.max_context; i++) {
|
||||
if ((g_isp_dev.ctx[i].dev_hdl) ==
|
||||
((struct cam_err_inject_param *)err_param)->dev_hdl) {
|
||||
cam_context_add_err_inject(&g_isp_dev.ctx[i], err_param);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
CAM_ERR(CAM_ISP, "no dev hdl found for IFE");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void cam_isp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -180,6 +196,9 @@ static int cam_isp_dev_component_bind(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
cam_common_register_err_inject_cb(cam_isp_dev_err_inject_cb,
|
||||
CAM_COMMON_ERR_INJECT_HW_ISP);
|
||||
|
||||
rc = cam_node_init(node, &hw_mgr_intf, g_isp_dev.ctx,
|
||||
g_isp_dev.max_context, CAM_ISP_DEV_NAME);
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <media/cam_sync.h>
|
||||
#include "cam_mem_mgr.h"
|
||||
#include "cam_jpeg_context.h"
|
||||
#include "cam_context_utils.h"
|
||||
@@ -97,6 +98,8 @@ static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx,
|
||||
if (rc)
|
||||
CAM_ERR(CAM_JPEG, "Unable to release device %d", rc);
|
||||
|
||||
cam_common_release_err_params(ctx->dev_hdl);
|
||||
|
||||
ctx->state = CAM_CTX_AVAILABLE;
|
||||
|
||||
return rc;
|
||||
@@ -153,6 +156,57 @@ static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_jpeg_context_inject_error(void *context, void *err_param)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_context *ctx = (struct cam_context *)context;
|
||||
uint64_t req_id;
|
||||
uint32_t err_code;
|
||||
uint32_t err_type;
|
||||
|
||||
if (!err_param) {
|
||||
CAM_ERR(CAM_ISP, "err_param not valid");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req_id = ((struct cam_err_inject_param *)err_param)->req_id;
|
||||
err_code = ((struct cam_err_inject_param *)err_param)->err_code;
|
||||
err_type = ((struct cam_err_inject_param *)err_param)->err_type;
|
||||
|
||||
switch (err_type) {
|
||||
case CAM_REQ_MGR_RETRY_EVENT:
|
||||
switch (err_code) {
|
||||
case CAM_REQ_MGR_JPEG_THUBNAIL_SIZE_ERROR:
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case CAM_SYNC_STATE_SIGNALED_ERROR:
|
||||
switch (err_code) {
|
||||
case CAM_SYNC_JPEG_EVENT_INVLD_CMD:
|
||||
case CAM_SYNC_JPEG_EVENT_SET_IRQ_CB:
|
||||
case CAM_SYNC_JPEG_EVENT_HW_RESET_FAILED:
|
||||
case CAM_SYNC_JPEG_EVENT_CDM_CHANGE_BASE_ERR:
|
||||
case CAM_SYNC_JPEG_EVENT_CDM_CONFIG_ERR:
|
||||
case CAM_SYNC_JPEG_EVENT_START_HW_ERR:
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_ISP, "err type not supported %d", err_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = cam_context_err_to_hw(ctx, err_param);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* top state machine */
|
||||
static struct cam_ctx_ops
|
||||
cam_jpeg_ctx_state_machine[CAM_CTX_STATE_MAX] = {
|
||||
@@ -184,6 +238,7 @@ static struct cam_ctx_ops
|
||||
.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
|
||||
.pagefault_ops = cam_jpeg_context_dump_active_request,
|
||||
.mini_dump_ops = cam_jpeg_context_mini_dump,
|
||||
.err_inject_ops = cam_jpeg_context_inject_error,
|
||||
},
|
||||
/* Ready */
|
||||
{
|
||||
|
@@ -16,11 +16,28 @@
|
||||
#include "cam_debug_util.h"
|
||||
#include "cam_smmu_api.h"
|
||||
#include "camera_main.h"
|
||||
#include "cam_common_util.h"
|
||||
|
||||
#define CAM_JPEG_DEV_NAME "cam-jpeg"
|
||||
|
||||
static struct cam_jpeg_dev g_jpeg_dev;
|
||||
|
||||
static int cam_jpeg_dev_err_inject_cb(void *err_param)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < CAM_JPEG_CTX_MAX; i++) {
|
||||
if (g_jpeg_dev.ctx[i].dev_hdl ==
|
||||
((struct cam_err_inject_param *)err_param)->dev_hdl) {
|
||||
CAM_INFO(CAM_ISP, "dev_hdl found:%d", g_jpeg_dev.ctx[i].dev_hdl);
|
||||
cam_context_add_err_inject(&g_jpeg_dev.ctx[i], err_param);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
CAM_ERR(CAM_ISP, "no dev hdl found jpeg");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void cam_jpeg_dev_iommu_fault_handler(
|
||||
struct cam_smmu_pf_info *pf_info)
|
||||
{
|
||||
@@ -155,6 +172,9 @@ static int cam_jpeg_dev_component_bind(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
cam_common_register_err_inject_cb(cam_jpeg_dev_err_inject_cb,
|
||||
CAM_COMMON_ERR_INJECT_HW_JPEG);
|
||||
|
||||
rc = cam_node_init(node, &hw_mgr_intf, g_jpeg_dev.ctx, CAM_JPEG_CTX_MAX,
|
||||
CAM_JPEG_DEV_NAME);
|
||||
if (rc) {
|
||||
|
@@ -56,6 +56,30 @@ static int cam_jpeg_insert_cdm_change_base(
|
||||
struct cam_jpeg_hw_ctx_data *ctx_data,
|
||||
struct cam_jpeg_hw_mgr *hw_mgr);
|
||||
|
||||
static void cam_jpeg_inject_err(struct cam_jpeg_hw_ctx_data *ctx_data,
|
||||
struct cam_hw_done_event_data *buf_data)
|
||||
{
|
||||
struct cam_req_mgr_message v4l2_msg = {0};
|
||||
struct cam_context *cam_ctx = ctx_data->context_priv;
|
||||
|
||||
if (ctx_data->err_inject_params.err_code == CAM_REQ_MGR_JPEG_THUBNAIL_SIZE_ERROR) {
|
||||
v4l2_msg.session_hdl = cam_ctx->session_hdl;
|
||||
v4l2_msg.u.node_msg.request_id = ctx_data->err_inject_params.err_req_id;
|
||||
v4l2_msg.u.node_msg.link_hdl = cam_ctx->link_hdl;
|
||||
v4l2_msg.u.node_msg.device_hdl = cam_ctx->dev_hdl;
|
||||
v4l2_msg.u.node_msg.event_type = CAM_REQ_MGR_RETRY_EVENT;
|
||||
v4l2_msg.u.node_msg.event_cause =
|
||||
CAM_REQ_MGR_JPEG_THUBNAIL_SIZE_ERROR;
|
||||
cam_req_mgr_notify_message(&v4l2_msg,
|
||||
V4L_EVENT_CAM_REQ_MGR_NODE_EVENT,
|
||||
V4L_EVENT_CAM_REQ_MGR_EVENT);
|
||||
} else {
|
||||
buf_data->evt_param = ctx_data->err_inject_params.err_code;
|
||||
}
|
||||
|
||||
memset(&(ctx_data->err_inject_params), 0, sizeof(struct cam_hw_err_param));
|
||||
}
|
||||
|
||||
static int cam_jpeg_generic_blob_handler(void *user_data,
|
||||
uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
|
||||
{
|
||||
@@ -617,6 +641,7 @@ static int cam_jpeg_mgr_release_ctx(
|
||||
}
|
||||
|
||||
ctx_data->in_use = false;
|
||||
memset(&(ctx_data->err_inject_params), 0, sizeof(struct cam_hw_err_param));
|
||||
mutex_unlock(&ctx_data->ctx_mutex);
|
||||
|
||||
return 0;
|
||||
@@ -781,6 +806,11 @@ static int cam_jpeg_mgr_process_hw_update_entries(void *priv, void *data)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ctx_data->err_inject_params.is_valid &&
|
||||
ctx_data->err_inject_params.err_req_id == request_id) {
|
||||
cam_jpeg_inject_err(ctx_data, &buf_data);
|
||||
goto end_callcb;
|
||||
}
|
||||
irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_sched_bottom_half;
|
||||
irq_cb.irq_cb_data.private_data = (void *)ctx_data;
|
||||
irq_cb.irq_cb_data.jpeg_req = jpeg_req;
|
||||
@@ -2217,6 +2247,19 @@ static int cam_jpeg_mgr_create_debugfs_entry(void)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cam_jpeg_mgr_inject_err(void *hw_mgr_priv, void *hw_err_inject_args)
|
||||
{
|
||||
struct cam_jpeg_hw_ctx_data *ctx_data = hw_mgr_priv;
|
||||
|
||||
ctx_data->err_inject_params.err_code = ((struct cam_err_inject_param *)
|
||||
hw_err_inject_args)->err_code;
|
||||
ctx_data->err_inject_params.err_type = ((struct cam_err_inject_param *)
|
||||
hw_err_inject_args)->err_type;
|
||||
ctx_data->err_inject_params.err_req_id = ((struct cam_err_inject_param *)
|
||||
hw_err_inject_args)->req_id;
|
||||
ctx_data->err_inject_params.is_valid = true;
|
||||
}
|
||||
|
||||
int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
int *iommu_hdl, cam_jpeg_mini_dump_cb mini_dump_cb)
|
||||
{
|
||||
@@ -2244,6 +2287,7 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop;
|
||||
hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd;
|
||||
hw_mgr_intf->hw_dump = cam_jpeg_mgr_hw_dump;
|
||||
hw_mgr_intf->hw_inject_err = cam_jpeg_mgr_inject_err;
|
||||
|
||||
mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
|
||||
spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);
|
||||
|
@@ -104,6 +104,7 @@ struct cam_jpeg_hw_cfg_req {
|
||||
* @wait_complete: Completion info
|
||||
* @cdm_cmd: Cdm cmd submitted for that context.
|
||||
* @mini_dump_cb: Mini dump cb
|
||||
* @err_inject_params: Error injection params for hw_mgr_ctx
|
||||
*/
|
||||
struct cam_jpeg_hw_ctx_data {
|
||||
void *context_priv;
|
||||
@@ -114,6 +115,7 @@ struct cam_jpeg_hw_ctx_data {
|
||||
struct completion wait_complete;
|
||||
struct cam_cdm_bl_request *cdm_cmd;
|
||||
cam_ctx_mini_dump_cb_func mini_dump_cb;
|
||||
struct cam_hw_err_param err_inject_params;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -22,6 +22,8 @@ static struct cam_common_mini_dump_dev_info g_minidump_dev_info;
|
||||
|
||||
#define CAM_PRESIL_POLL_DELAY 20
|
||||
|
||||
static struct cam_common_err_inject_info g_err_inject_info;
|
||||
|
||||
static uint timeout_multiplier = 1;
|
||||
module_param(timeout_multiplier, uint, 0644);
|
||||
|
||||
@@ -336,3 +338,202 @@ int cam_common_user_dump_helper(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_common_register_err_inject_cb(
|
||||
cam_common_err_inject_cb err_inject_cb,
|
||||
enum cam_common_err_inject_hw_id hw_id)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (g_err_inject_info.num_hw_registered >= CAM_COMMON_ERR_INJECT_HW_MAX) {
|
||||
CAM_ERR(CAM_UTIL, "No free index available");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!err_inject_cb || hw_id >= CAM_COMMON_ERR_INJECT_HW_MAX) {
|
||||
CAM_ERR(CAM_UTIL, "Invalid params");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
g_err_inject_info.err_inject_cb[hw_id] = err_inject_cb;
|
||||
g_err_inject_info.num_hw_registered++;
|
||||
CAM_DBG(CAM_UTIL, "err inject cb registered for HW_id:%d, total registered: %d", hw_id,
|
||||
g_err_inject_info.num_hw_registered);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cam_common_release_err_params(uint64_t dev_hdl)
|
||||
{
|
||||
int rc = 0;
|
||||
struct list_head *pos = NULL, *pos_next = NULL;
|
||||
struct cam_err_inject_param *err_param;
|
||||
|
||||
if (!g_err_inject_info.is_list_initialised)
|
||||
return -EINVAL;
|
||||
|
||||
if (list_empty(&g_err_inject_info.active_err_ctx_list)) {
|
||||
CAM_ERR(CAM_UTIL, "list is empty");
|
||||
return -EINVAL;
|
||||
}
|
||||
list_for_each_safe(pos, pos_next, &g_err_inject_info.active_err_ctx_list) {
|
||||
err_param = list_entry(pos, struct cam_err_inject_param, list);
|
||||
if (err_param->dev_hdl == dev_hdl) {
|
||||
CAM_INFO(CAM_UTIL, "entry deleted for %llu dev hdl", dev_hdl);
|
||||
list_del(pos);
|
||||
kfree(err_param);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_err_inject_set(const char *kmessage,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
int rc = 0;
|
||||
char tmp_buff[CAM_COMMON_ERR_INJECT_BUFFER_LEN] = {'\0'};
|
||||
char *token_start, *token_end;
|
||||
struct cam_err_inject_param *err_params = NULL;
|
||||
uint8_t param_counter = 0;
|
||||
|
||||
err_params = kzalloc(sizeof(struct cam_err_inject_param), GFP_KERNEL);
|
||||
if (!err_params) {
|
||||
CAM_ERR(CAM_UTIL, "no free memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(tmp_buff, 0, CAM_COMMON_ERR_INJECT_BUFFER_LEN);
|
||||
rc = strscpy(tmp_buff, kmessage, CAM_COMMON_ERR_INJECT_BUFFER_LEN);
|
||||
if (rc == -E2BIG)
|
||||
goto free;
|
||||
|
||||
token_start = tmp_buff;
|
||||
token_end = tmp_buff;
|
||||
|
||||
CAM_INFO(CAM_UTIL, "parsing input param for cam_err_inject: %s", tmp_buff);
|
||||
while (token_start != NULL) {
|
||||
strsep(&token_end, ":");
|
||||
switch (param_counter) {
|
||||
case HW_NAME:
|
||||
if (strcmp(token_start, CAM_COMMON_IFE_NODE) == 0)
|
||||
err_params->hw_id = CAM_COMMON_ERR_INJECT_HW_ISP;
|
||||
else if (strcmp(token_start, CAM_COMMON_ICP_NODE) == 0)
|
||||
err_params->hw_id = CAM_COMMON_ERR_INJECT_HW_ICP;
|
||||
else if (strcmp(token_start, CAM_COMMON_JPEG_NODE) == 0)
|
||||
err_params->hw_id = CAM_COMMON_ERR_INJECT_HW_JPEG;
|
||||
else {
|
||||
CAM_ERR(CAM_UTIL, "invalid camera hardware [ %s ]", token_start);
|
||||
goto free;
|
||||
}
|
||||
break;
|
||||
case REQ_ID:
|
||||
if (kstrtou64(token_start, 0, &(err_params->req_id)))
|
||||
goto free;
|
||||
break;
|
||||
case ERR_TYPE:
|
||||
if (kstrtou32(token_start, 0, &(err_params->err_type)))
|
||||
goto free;
|
||||
break;
|
||||
case ERR_CODE:
|
||||
if (kstrtou32(token_start, 0, &(err_params->err_code)))
|
||||
goto free;
|
||||
break;
|
||||
case DEV_HDL:
|
||||
if (kstrtou64(token_start, 0, &(err_params->dev_hdl)))
|
||||
goto free;
|
||||
break;
|
||||
default:
|
||||
CAM_ERR(CAM_UTIL, "Insuffiecient parameter count [%d] ", param_counter);
|
||||
goto free;
|
||||
}
|
||||
|
||||
param_counter++;
|
||||
token_start = token_end;
|
||||
}
|
||||
|
||||
if (param_counter < CAM_COMMON_ERR_INJECT_PARAM_NUM) {
|
||||
CAM_ERR(CAM_UTIL, "Insuffiecient parameter count [%d]", param_counter);
|
||||
goto free;
|
||||
}
|
||||
|
||||
CAM_INFO(CAM_UTIL, "parsed params: req_id: %llu err_type: %u, err_code: %u dev_hdl: %llu",
|
||||
err_params->req_id, err_params->err_type, err_params->err_code,
|
||||
err_params->dev_hdl);
|
||||
|
||||
if (g_err_inject_info.err_inject_cb[err_params->hw_id]) {
|
||||
rc = g_err_inject_info.err_inject_cb[err_params->hw_id](err_params);
|
||||
if (rc)
|
||||
goto free;
|
||||
else {
|
||||
if (!g_err_inject_info.is_list_initialised) {
|
||||
INIT_LIST_HEAD(&g_err_inject_info.active_err_ctx_list);
|
||||
g_err_inject_info.is_list_initialised = true;
|
||||
}
|
||||
|
||||
list_add(&err_params->list, &g_err_inject_info.active_err_ctx_list);
|
||||
}
|
||||
} else {
|
||||
CAM_ERR(CAM_UTIL, "Handler for HW_id [%d] not registered", err_params->hw_id);
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
CAM_ERR(CAM_UTIL, "No Dev_hdl found: [%d]", err_params->dev_hdl);
|
||||
|
||||
return rc;
|
||||
free:
|
||||
kfree(err_params);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cam_err_inject_get(char *buffer,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
uint8_t hw_name[10];
|
||||
uint16_t buff_max_size = CAM_COMMON_ERR_MODULE_PARAM_MAX_LENGTH;
|
||||
struct cam_err_inject_param *err_param;
|
||||
int ret = 0;
|
||||
|
||||
if (!g_err_inject_info.is_list_initialised)
|
||||
return scnprintf(buffer, buff_max_size, "uninitialised");
|
||||
|
||||
else if (!list_empty(&g_err_inject_info.active_err_ctx_list)) {
|
||||
list_for_each_entry(err_param, &g_err_inject_info.active_err_ctx_list, list) {
|
||||
switch (err_param->hw_id) {
|
||||
case CAM_COMMON_ERR_INJECT_HW_ISP:
|
||||
strscpy(hw_name, CAM_COMMON_IFE_NODE, 10);
|
||||
break;
|
||||
case CAM_COMMON_ERR_INJECT_HW_ICP:
|
||||
strscpy(hw_name, CAM_COMMON_ICP_NODE, 10);
|
||||
break;
|
||||
case CAM_COMMON_ERR_INJECT_HW_JPEG:
|
||||
strscpy(hw_name, CAM_COMMON_JPEG_NODE, 10);
|
||||
break;
|
||||
default:
|
||||
strscpy(hw_name, "undef", 10);
|
||||
}
|
||||
ret += scnprintf(buffer+ret, buff_max_size,
|
||||
"hw_name: %s req_id: %u err_type: %u err_code: %u dev_hdl: %d\n",
|
||||
hw_name, err_param->req_id, err_param->err_type,
|
||||
err_param->err_code, err_param->dev_hdl);
|
||||
|
||||
CAM_DBG(CAM_UTIL, "output buffer: %s", buffer);
|
||||
|
||||
if (ret < buff_max_size) {
|
||||
buff_max_size = buff_max_size - ret;
|
||||
} else {
|
||||
CAM_WARN(CAM_UTIL, "out buff max limit reached");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return scnprintf(buffer, buff_max_size, "uninitialised");
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops cam_error_inject_ops = {
|
||||
.set = cam_err_inject_set,
|
||||
.get = cam_err_inject_get
|
||||
};
|
||||
|
||||
module_param_cb(cam_error_inject, &cam_error_inject_ops, NULL, 0644);
|
||||
|
@@ -19,6 +19,14 @@
|
||||
|
||||
#define CAM_COMMON_HW_DUMP_TAG_MAX_LEN 64
|
||||
|
||||
#define CAM_COMMON_ERR_MODULE_PARAM_MAX_LENGTH 4096
|
||||
#define CAM_COMMON_ERR_INJECT_BUFFER_LEN 200
|
||||
#define CAM_COMMON_ERR_INJECT_DEV_MAX 5
|
||||
#define CAM_COMMON_ERR_INJECT_PARAM_NUM 5
|
||||
#define CAM_COMMON_IFE_NODE "IFE"
|
||||
#define CAM_COMMON_ICP_NODE "IPE"
|
||||
#define CAM_COMMON_JPEG_NODE "JPEG"
|
||||
|
||||
#define PTR_TO_U64(ptr) ((uint64_t)(uintptr_t)ptr)
|
||||
#define U64_TO_PTR(ptr) ((void *)(uintptr_t)ptr)
|
||||
|
||||
@@ -78,6 +86,54 @@ struct cam_common_mini_dump_data {
|
||||
unsigned long size[CAM_COMMON_MINI_DUMP_DEV_NUM];
|
||||
};
|
||||
|
||||
|
||||
typedef int (*cam_common_err_inject_cb) (void *err_param);
|
||||
int cam_common_release_err_params(uint64_t dev_hdl);
|
||||
|
||||
enum cam_common_err_inject_hw_id {
|
||||
CAM_COMMON_ERR_INJECT_HW_ISP,
|
||||
CAM_COMMON_ERR_INJECT_HW_ICP,
|
||||
CAM_COMMON_ERR_INJECT_HW_JPEG,
|
||||
CAM_COMMON_ERR_INJECT_HW_MAX
|
||||
};
|
||||
|
||||
enum cam_common_err_inject_input_param_pos {
|
||||
HW_NAME = 0,
|
||||
REQ_ID,
|
||||
ERR_TYPE,
|
||||
ERR_CODE,
|
||||
DEV_HDL
|
||||
};
|
||||
|
||||
/**
|
||||
* @req_id : req id for err to be injected
|
||||
* @dev_hdl : dev_hdl for the context
|
||||
* @err_type: error type for error request
|
||||
* @err_code: error code for error request
|
||||
* @hw_id : hw id representing hw nodes of type cam_common_err_inject_hw_id
|
||||
*/
|
||||
struct cam_err_inject_param {
|
||||
struct list_head list;
|
||||
uint64_t req_id;
|
||||
uint64_t dev_hdl;
|
||||
uint32_t err_type;
|
||||
uint32_t err_code;
|
||||
uint8_t hw_id;
|
||||
};
|
||||
/**
|
||||
* struct cam_common_err_inject_info
|
||||
* @err_inject_cb : address of callback
|
||||
* @active_err_ctx_list: list containing active err inject requests
|
||||
* @num_hw_registered : number of callbacks registered
|
||||
* @is_list_initialised: bool to check init for err_inject list
|
||||
*/
|
||||
struct cam_common_err_inject_info {
|
||||
cam_common_err_inject_cb err_inject_cb[CAM_COMMON_ERR_INJECT_HW_MAX];
|
||||
struct list_head active_err_ctx_list;
|
||||
uint8_t num_hw_registered;
|
||||
bool is_list_initialised;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_common_hw_dump_args
|
||||
* @req_id : request id
|
||||
@@ -258,4 +314,18 @@ int cam_common_user_dump_helper(
|
||||
const char *tag,
|
||||
...);
|
||||
|
||||
/**
|
||||
* cam_common_register_err_inject_cb()
|
||||
*
|
||||
* @brief common interface to register error inject cb
|
||||
*
|
||||
* @err_inject_cb: Pointer to err_inject_cb
|
||||
* @hw_id: HW id of the HW driver registering
|
||||
*
|
||||
* @return: 0 if success in register non-zero if failes
|
||||
*/
|
||||
int cam_common_register_err_inject_cb(
|
||||
cam_common_err_inject_cb err_inject_cb,
|
||||
enum cam_common_err_inject_hw_id hw_id);
|
||||
|
||||
#endif /* _CAM_COMMON_UTIL_H_ */
|
||||
|
Viittaa uudesa ongelmassa
Block a user