msm: camera: common: Enhance error injection framework

Update from error injection framework to event injection framework to
support PF event inducement and node event. Different set of user
input parameters are required dependent on which event to injection.

ICP and ISP support error event and page fault event injection. JPEG
supports node event and page fault event injection. However, buf done
error injection is only supported for JPEG and ICP.

Create a query API to check whether PF is fatal for a context bank.
Using the API, if PF is fatal, page fault event injection is not
supported for the device that owns the context bank.

Make change to JPEG context event callback handling to account for
various events including Event Injection event.

CRs-Fixed: 3210139
Change-Id: I582ee0bda8dbf631ece2522a5a8145f38ec71928
Signed-off-by: Sokchetra Eung <quic_eung@quicinc.com>
This commit is contained in:
Sokchetra Eung
2022-05-24 17:50:49 -07:00
committed by Camera Software Integration
parent 4e06429fc8
commit c87d8891b9
22 changed files with 1237 additions and 472 deletions

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/string.h>
@@ -22,10 +23,13 @@ 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 struct cam_common_inject_evt_info g_inject_evt_info;
static uint timeout_multiplier = 1;
module_param(timeout_multiplier, uint, 0644);
typedef int (*cam_common_evt_inject_cmd_parse_handler)(
struct cam_common_inject_evt_param *inject_params,
uint32_t param_counter, char *token);
int cam_common_util_get_string_index(const char **strings,
uint32_t num_strings, const char *matching_string, uint32_t *index)
@@ -339,201 +343,483 @@ 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 cam_common_register_evt_inject_cb(cam_common_evt_inject_cb evt_inject_cb,
enum cam_common_evt_inject_hw_id hw_id)
{
int rc = 0;
if (g_err_inject_info.num_hw_registered >= CAM_COMMON_ERR_INJECT_HW_MAX) {
if (g_inject_evt_info.num_hw_registered >= CAM_COMMON_EVT_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");
if (!evt_inject_cb || hw_id >= CAM_COMMON_EVT_INJECT_HW_MAX) {
CAM_ERR(CAM_UTIL, "Invalid params evt_inject_cb %s hw_id: %d",
CAM_IS_NULL_TO_STR(evt_inject_cb), hw_id);
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);
g_inject_evt_info.evt_inject_cb[hw_id] = evt_inject_cb;
g_inject_evt_info.num_hw_registered++;
CAM_DBG(CAM_UTIL, "Evt inject cb registered for HW_id: %d, total registered: %d", hw_id,
g_inject_evt_info.num_hw_registered);
return rc;
}
int cam_common_release_err_params(uint64_t dev_hdl)
void cam_common_release_evt_params(int32_t dev_hdl)
{
int rc = 0;
struct list_head *pos = NULL, *pos_next = NULL;
struct cam_err_inject_param *err_param;
struct cam_common_inject_evt_param *inject_params;
if (!g_err_inject_info.is_list_initialised)
return -EINVAL;
if (!g_inject_evt_info.is_list_initialised)
return;
if (list_empty(&g_err_inject_info.active_err_ctx_list)) {
CAM_ERR(CAM_UTIL, "list is empty");
return -EINVAL;
if (list_empty(&g_inject_evt_info.active_evt_ctx_list)) {
CAM_DBG(CAM_UTIL, "Event injection list is initialized but empty");
return;
}
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_for_each_safe(pos, pos_next, &g_inject_evt_info.active_evt_ctx_list) {
inject_params = list_entry(pos, struct cam_common_inject_evt_param, list);
if (inject_params->dev_hdl == dev_hdl) {
CAM_INFO(CAM_UTIL, "entry deleted for %d dev hdl", dev_hdl);
list_del(pos);
kfree(err_param);
kfree(inject_params);
}
}
}
static inline int cam_common_evt_inject_get_hw_id(uint8_t *hw_id, char *token)
{
if (strcmp(token, CAM_COMMON_IFE_NODE) == 0)
*hw_id = CAM_COMMON_EVT_INJECT_HW_ISP;
else if (strcmp(token, CAM_COMMON_ICP_NODE) == 0)
*hw_id = CAM_COMMON_EVT_INJECT_HW_ICP;
else if (strcmp(token, CAM_COMMON_JPEG_NODE) == 0)
*hw_id = CAM_COMMON_EVT_INJECT_HW_JPEG;
else {
CAM_ERR(CAM_UTIL, "Invalid camera hardware [ %s ]", token);
return -EINVAL;
}
return 0;
}
static inline int cam_common_evt_inject_get_str_id_type(uint8_t *id_type, char *token)
{
if (!strcmp(token, CAM_COMMON_EVT_INJECT_BUFFER_ERROR))
*id_type = CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE;
else if (!strcmp(token, CAM_COMMON_EVT_INJECT_NOTIFY_EVENT))
*id_type = CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE;
else {
CAM_ERR(CAM_UTIL, "Invalid string id: %s", token);
return -EINVAL;
}
return 0;
}
static int cam_common_evt_inject_parse_buffer_error_evt_params(
struct cam_common_inject_evt_param *inject_params,
uint32_t param_counter, char *token)
{
struct cam_hw_inject_buffer_error_param *buf_err_params =
&inject_params->evt_params.u.buf_err_evt;
int rc = 0;
switch (param_counter) {
case SYNC_ERROR_CAUSE:
if (kstrtou32(token, 0, &buf_err_params->sync_error)) {
CAM_ERR(CAM_UTIL, "Invalid event type %s", token);
rc = -EINVAL;
}
break;
default:
CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
rc = -EINVAL;
}
return rc;
}
static int cam_err_inject_set(const char *kmessage,
static int cam_common_evt_inject_parse_node_evt_params(
struct cam_common_inject_evt_param *inject_params,
uint32_t param_counter, char *token)
{
struct cam_hw_inject_node_evt_param *node_params =
&inject_params->evt_params.u.evt_notify.u.node_evt_params;
int rc = 0;
switch (param_counter) {
case EVENT_TYPE:
if (kstrtou32(token, 0, &node_params->event_type)) {
CAM_ERR(CAM_UTIL, "Invalid event type %s", token);
rc = -EINVAL;
}
break;
case EVENT_CAUSE:
if (kstrtou32(token, 0, &node_params->event_cause)) {
CAM_ERR(CAM_UTIL, "Invalid event cause %s", token);
rc = -EINVAL;
}
break;
default:
CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
rc = -EINVAL;
}
return rc;
}
static int cam_common_evt_inject_parse_pf_params(
struct cam_common_inject_evt_param *inject_params,
uint32_t param_counter, char *token)
{
struct cam_hw_inject_pf_evt_param *pf_params =
&inject_params->evt_params.u.evt_notify.u.pf_evt_params;
int rc = 0;
switch (param_counter) {
case PF_PARAM_CTX_FOUND:
if (kstrtobool(token, &pf_params->ctx_found)) {
CAM_ERR(CAM_UTIL, "Invalid context found value %s", token);
rc = -EINVAL;
}
break;
default:
CAM_ERR(CAM_UTIL, "Invalid extra parameters %s", token);
rc = -EINVAL;
}
return rc;
}
static int cam_common_evt_inject_parse_err_evt_params(
struct cam_common_inject_evt_param *inject_params,
uint32_t param_counter, char *token)
{
struct cam_hw_inject_err_evt_param *err_params =
&inject_params->evt_params.u.evt_notify.u.err_evt_params;
int rc = 0;
switch (param_counter) {
case ERR_PARAM_ERR_TYPE:
if (kstrtou32(token, 0, &err_params->err_type)) {
CAM_ERR(CAM_UTIL, "Invalid error type %s", token);
rc = -EINVAL;
}
break;
case ERR_PARAM_ERR_CODE:
if (kstrtou32(token, 0, &err_params->err_code)) {
CAM_ERR(CAM_UTIL, "Invalid error code %s", token);
rc = -EINVAL;
}
break;
default:
CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
rc = -EINVAL;
}
return rc;
}
static int cam_common_evt_inject_parse_event_notify(
struct cam_common_inject_evt_param *inject_params,
uint32_t param_counter, char *token)
{
int rc = 0;
switch (param_counter) {
case EVT_NOTIFY_TYPE:
if (kstrtou32(token, 0,
&inject_params->evt_params.u.evt_notify.evt_notify_type)) {
CAM_ERR(CAM_UTIL, "Invalid Event notify type %s", token);
rc = -EINVAL;
}
break;
default:
CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
rc = -EINVAL;
}
return rc;
}
static int cam_common_evt_inject_parse_common_params(
struct cam_common_inject_evt_param *inject_params,
uint32_t param_counter, char *token)
{
int rc = 0;
struct cam_hw_inject_evt_param *evt_param = &inject_params->evt_params;
switch (param_counter) {
case STRING_ID:
rc = cam_common_evt_inject_get_str_id_type(&evt_param->inject_id, token);
break;
case HW_NAME:
rc = cam_common_evt_inject_get_hw_id(&inject_params->hw_id, token);
break;
case DEV_HDL:
if (kstrtos32(token, 0, &inject_params->dev_hdl)) {
CAM_ERR(CAM_UTIL, "Invalid device handle %s", token);
rc = -EINVAL;
}
break;
case REQ_ID:
if (kstrtou64(token, 0, &evt_param->req_id)) {
CAM_ERR(CAM_UTIL, "Invalid request id %s", token);
rc = -EINVAL;
}
break;
default:
CAM_ERR(CAM_UTIL, "Invalid extra parameter: %s", token);
rc = -EINVAL;
}
return rc;
}
static int cam_common_evt_inject_generic_command_parser(
struct cam_common_inject_evt_param *inject_params,
char **msg, uint32_t max_params, cam_common_evt_inject_cmd_parse_handler cmd_parse_cb)
{
char *token = NULL;
int rc = 0, param_counter = 0;
token = strsep(msg, ":");
while (token != NULL) {
rc = cmd_parse_cb(inject_params, param_counter, token);
if (rc) {
CAM_ERR(CAM_UTIL, "Parsed Command failed rc: %d", rc);
return rc;
}
param_counter++;
if (param_counter == max_params)
break;
token = strsep(msg, ":");
}
if (param_counter < max_params) {
CAM_ERR(CAM_UTIL,
"Insufficient parameters passed for total parameters: %u",
param_counter);
return -EINVAL;
}
return rc;
}
static int cam_common_evt_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;
struct cam_common_inject_evt_param *inject_params = NULL;
struct cam_hw_inject_evt_param *hw_evt_params = NULL;
cam_common_evt_inject_cmd_parse_handler parse_handler = NULL;
int rc = 0;
char tmp_buff[CAM_COMMON_EVT_INJECT_BUFFER_LEN];
char *msg = NULL;
uint32_t param_output = 0;
err_params = kzalloc(sizeof(struct cam_err_inject_param), GFP_KERNEL);
if (!err_params) {
inject_params = kzalloc(sizeof(struct cam_common_inject_evt_param), GFP_KERNEL);
if (!inject_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);
rc = strscpy(tmp_buff, kmessage, CAM_COMMON_EVT_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 event injection: %s", 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;
}
msg = tmp_buff;
hw_evt_params = &inject_params->evt_params;
rc = cam_common_evt_inject_generic_command_parser(inject_params, &msg,
COMMON_PARAM_MAX, cam_common_evt_inject_parse_common_params);
if (rc) {
CAM_ERR(CAM_UTIL, "Fail to parse common params %d", rc);
goto free;
}
switch (hw_evt_params->inject_id) {
case CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE:
rc = cam_common_evt_inject_generic_command_parser(inject_params, &msg,
EVT_NOTIFY_PARAM_MAX, cam_common_evt_inject_parse_event_notify);
if (rc) {
CAM_ERR(CAM_UTIL, "Fail to parse event notify type param %d", rc);
goto free;
}
switch (hw_evt_params->u.evt_notify.evt_notify_type) {
case V4L_EVENT_CAM_REQ_MGR_ERROR:
parse_handler = cam_common_evt_inject_parse_err_evt_params;
param_output = ERR_PARAM_MAX;
break;
case REQ_ID:
if (kstrtou64(token_start, 0, &(err_params->req_id)))
goto free;
case V4L_EVENT_CAM_REQ_MGR_NODE_EVENT:
parse_handler = cam_common_evt_inject_parse_node_evt_params;
param_output = NODE_PARAM_MAX;
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;
case V4L_EVENT_CAM_REQ_MGR_PF_ERROR:
parse_handler = cam_common_evt_inject_parse_pf_params;
param_output = PF_PARAM_MAX;
break;
default:
CAM_ERR(CAM_UTIL, "Insuffiecient parameter count [%d] ", param_counter);
CAM_ERR(CAM_UTIL, "Invalid event notification type: %u",
hw_evt_params->u.evt_notify.evt_notify_type);
goto free;
}
param_counter++;
token_start = token_end;
break;
case CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE:
parse_handler = cam_common_evt_inject_parse_buffer_error_evt_params;
param_output = BUFFER_ERROR_PARAM_MAX;
break;
default:
CAM_ERR(CAM_UTIL, "Invalid Injection id: %u", hw_evt_params->inject_id);
}
if (param_counter < CAM_COMMON_ERR_INJECT_PARAM_NUM) {
CAM_ERR(CAM_UTIL, "Insuffiecient parameter count [%d]", param_counter);
rc = cam_common_evt_inject_generic_command_parser(inject_params, &msg,
param_output, parse_handler);
if (rc) {
CAM_ERR(CAM_UTIL, "Command Parsed failed with Inject id: %u rc: %d",
hw_evt_params->inject_id, rc);
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 (g_inject_evt_info.evt_inject_cb[inject_params->hw_id]) {
rc = g_inject_evt_info.evt_inject_cb[inject_params->hw_id](inject_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);
CAM_ERR(CAM_UTIL, "Handler for HW_id [%hhu] not registered", inject_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;
if (!g_inject_evt_info.is_list_initialised) {
INIT_LIST_HEAD(&g_inject_evt_info.active_evt_ctx_list);
g_inject_evt_info.is_list_initialised = true;
}
return scnprintf(buffer, buff_max_size, "uninitialised");
list_add(&inject_params->list, &g_inject_evt_info.active_evt_ctx_list);
return rc;
free:
kfree(inject_params);
return rc;
}
static const struct kernel_param_ops cam_error_inject_ops = {
.set = cam_err_inject_set,
.get = cam_err_inject_get
static int cam_common_evt_inject_get(char *buffer,
const struct kernel_param *kp)
{
uint8_t hw_name[16], string_id[16];
uint16_t buff_max_size = CAM_COMMON_EVT_INJECT_MODULE_PARAM_MAX_LENGTH;
struct cam_common_inject_evt_param *inject_params = NULL;
struct cam_hw_inject_evt_param *evt_params = NULL;
uint32_t ret = 0;
if (!g_inject_evt_info.is_list_initialised)
return scnprintf(buffer, buff_max_size, "uninitialised");
if (list_empty(&g_inject_evt_info.active_evt_ctx_list))
return scnprintf(buffer, buff_max_size, "Active err inject list is empty");
list_for_each_entry(inject_params, &g_inject_evt_info.active_evt_ctx_list, list) {
evt_params = &inject_params->evt_params;
switch (inject_params->hw_id) {
case CAM_COMMON_EVT_INJECT_HW_ISP:
strscpy(hw_name, CAM_COMMON_IFE_NODE, sizeof(hw_name));
break;
case CAM_COMMON_EVT_INJECT_HW_ICP:
strscpy(hw_name, CAM_COMMON_ICP_NODE, sizeof(hw_name));
break;
case CAM_COMMON_EVT_INJECT_HW_JPEG:
strscpy(hw_name, CAM_COMMON_JPEG_NODE, sizeof(hw_name));
break;
default:
ret += scnprintf(buffer+ret, buff_max_size, "Undefined HW id\n");
goto undefined_param;
}
switch (evt_params->inject_id) {
case CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE:
strscpy(string_id, CAM_COMMON_EVT_INJECT_BUFFER_ERROR, sizeof(string_id));
break;
case CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE:
strscpy(string_id, CAM_COMMON_EVT_INJECT_NOTIFY_EVENT, sizeof(string_id));
break;
default:
ret += scnprintf(buffer+ret, buff_max_size, "Undefined string id\n");
goto undefined_param;
}
ret += scnprintf(buffer+ret, buff_max_size,
"string_id: %s hw_name: %s dev_hdl: %d req_id: %llu ",
string_id, hw_name,
inject_params->dev_hdl, evt_params->req_id);
if (buff_max_size > ret) {
buff_max_size -= ret;
} else {
CAM_WARN(CAM_UTIL, "out buff max limit reached");
break;
}
if (evt_params->inject_id ==
CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE) {
ret += scnprintf(buffer+ret, buff_max_size,
"sync_error: %u\n", evt_params->u.buf_err_evt.sync_error);
} else {
switch (evt_params->u.evt_notify.evt_notify_type) {
case V4L_EVENT_CAM_REQ_MGR_ERROR: {
struct cam_hw_inject_err_evt_param *err_evt_params =
&evt_params->u.evt_notify.u.err_evt_params;
ret += scnprintf(buffer+ret, buff_max_size,
"Error event: error type: %u error code: %u\n",
err_evt_params->err_type, err_evt_params->err_code);
break;
}
case V4L_EVENT_CAM_REQ_MGR_NODE_EVENT: {
struct cam_hw_inject_node_evt_param *node_evt_params =
&evt_params->u.evt_notify.u.node_evt_params;
ret += scnprintf(buffer+ret, buff_max_size,
"Node event: event type: %u event cause: %u\n",
node_evt_params->event_type, node_evt_params->event_cause);
break;
}
case V4L_EVENT_CAM_REQ_MGR_PF_ERROR: {
struct cam_hw_inject_pf_evt_param *pf_evt_params =
&evt_params->u.evt_notify.u.pf_evt_params;
ret += scnprintf(buffer+ret, buff_max_size,
"PF event: ctx found %hhu\n",
pf_evt_params->ctx_found);
break;
}
default:
ret += scnprintf(buffer+ret, buff_max_size,
"Undefined notification event\n");
}
}
undefined_param:
CAM_DBG(CAM_UTIL, "output buffer: %s", buffer);
if (buff_max_size > ret) {
buff_max_size -= ret;
} else {
CAM_WARN(CAM_UTIL, "out buff max limit reached");
break;
}
}
return ret;
}
static const struct kernel_param_ops cam_common_evt_inject = {
.set = cam_common_evt_inject_set,
.get = cam_common_evt_inject_get
};
module_param_cb(cam_error_inject, &cam_error_inject_ops, NULL, 0644);
module_param_cb(cam_event_inject, &cam_common_evt_inject, NULL, 0644);

View File

@@ -10,6 +10,8 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include "cam_hw_mgr_intf.h"
#define CAM_BITS_MASK_SHIFT(x, mask, shift) (((x) & (mask)) >> shift)
#define CAM_36BIT_INTF_GET_IOVA_BASE(iova) ((iova) >> 8)
#define CAM_36BIT_INTF_GET_IOVA_OFFSET(iova) ((iova) & 0xff)
@@ -21,12 +23,12 @@
#define CAM_COMMON_HW_DUMP_TAG_MAX_LEN 64
#define CAM_MAX_NUM_CCI_PAYLOAD_BYTES 11
#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_EVT_INJECT_MODULE_PARAM_MAX_LENGTH 4096
#define CAM_COMMON_EVT_INJECT_BUFFER_LEN 200
#define CAM_COMMON_EVT_INJECT_BUFFER_ERROR "Buffer_Error"
#define CAM_COMMON_EVT_INJECT_NOTIFY_EVENT "Notify_Event"
#define CAM_COMMON_IFE_NODE "IFE"
#define CAM_COMMON_ICP_NODE "IPE"
#define CAM_COMMON_JPEG_NODE "JPEG"
#define CAM_COMMON_NS_PER_MS 1000000ULL
@@ -110,49 +112,91 @@ struct cam_common_mini_dump_data {
};
typedef int (*cam_common_err_inject_cb) (void *err_param);
int cam_common_release_err_params(uint64_t dev_hdl);
typedef int (*cam_common_evt_inject_cb) (void *inject_args);
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_evt_inject_str_id_type {
CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE,
CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE
};
enum cam_common_err_inject_input_param_pos {
HW_NAME = 0,
enum cam_common_evt_inject_hw_id {
CAM_COMMON_EVT_INJECT_HW_ISP,
CAM_COMMON_EVT_INJECT_HW_ICP,
CAM_COMMON_EVT_INJECT_HW_JPEG,
CAM_COMMON_EVT_INJECT_HW_MAX
};
enum cam_common_evt_inject_common_param_pos {
STRING_ID,
HW_NAME,
DEV_HDL,
REQ_ID,
ERR_TYPE,
ERR_CODE,
DEV_HDL
COMMON_PARAM_MAX
};
enum cam_common_evt_inject_notify_event_pos {
EVT_NOTIFY_TYPE,
EVT_NOTIFY_PARAM_MAX
};
enum cam_evt_inject_buffer_error_event {
SYNC_ERROR_CAUSE,
BUFFER_ERROR_PARAM_MAX
};
enum cam_evt_inject_error_param_pos {
ERR_PARAM_ERR_TYPE,
ERR_PARAM_ERR_CODE,
ERR_PARAM_MAX
};
enum cam_evt_inject_node_param_pos {
EVENT_TYPE,
EVENT_CAUSE,
NODE_PARAM_MAX,
};
enum cam_evt_inject_pf_params_pos {
PF_PARAM_CTX_FOUND,
PF_PARAM_MAX
};
/**
* @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_common_evt_inject_data
* @buf_done_data: buf done data
* @evt_params : event params for the injected event
*/
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_evt_inject_data {
void *buf_done_data;
struct cam_hw_inject_evt_param *evt_params;
};
typedef int (*cam_common_evt_inject_ops) (void *cam_ctx,
struct cam_common_evt_inject_data *inject_evt);
/**
* 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_inject_evt_param
* @evt_params : injection event params
* @dev_hdl : device handle to match with ctx's dev_hdl
* @hw_id : hw to be injected with the event
*/
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;
struct cam_common_inject_evt_param {
struct list_head list;
struct cam_hw_inject_evt_param evt_params;
int32_t dev_hdl;
uint8_t hw_id;
};
/**
* struct cam_common_inject_evt_info
* @evt_inject_cb : address of callback
* @active_err_ctx_list: list containing active evt inject requests
* @num_hw_registered : number of callbacks registered
* @is_list_initialised: bool to check init for evt_inject list
*/
struct cam_common_inject_evt_info {
cam_common_evt_inject_cb evt_inject_cb[CAM_COMMON_EVT_INJECT_HW_MAX];
struct list_head active_evt_ctx_list;
uint8_t num_hw_registered;
bool is_list_initialised;
};
@@ -189,6 +233,13 @@ struct cam_common_hw_dump_header {
uint32_t word_size;
};
/**
* @brief release all event inject params in the g_inject_evt_info
* for a specific dev_hdl
* @dev_hdl: device handle to which the evt inject params belong to
*/
void cam_common_release_evt_params(int32_t dev_hdl);
/**
* cam_common_util_get_string_index()
*
@@ -338,17 +389,17 @@ int cam_common_user_dump_helper(
...);
/**
* cam_common_register_err_inject_cb()
* cam_common_register_evt_inject_cb()
*
* @brief common interface to register error inject cb
* @brief common interface to register evt inject cb
*
* @err_inject_cb: Pointer to err_inject_cb
* @evt_inject_cb: Pointer to evt_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);
int cam_common_register_evt_inject_cb(
cam_common_evt_inject_cb evt_inject_cb,
enum cam_common_evt_inject_hw_id hw_id);
#endif /* _CAM_COMMON_UTIL_H_ */