diff --git a/drivers/cam_icp/cam_icp_context.c b/drivers/cam_icp/cam_icp_context.c index 41d1ffe483..42f1304a35 100644 --- a/drivers/cam_icp/cam_icp_context.c +++ b/drivers/cam_icp/cam_icp_context.c @@ -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 @@ -19,6 +20,8 @@ #include "cam_trace.h" #include "cam_debug_util.h" #include "cam_packet_util.h" +#include "cam_req_mgr_dev.h" +#include "cam_icp_hw_mgr_intf.h" static const char icp_dev_name[] = "cam-icp"; @@ -234,10 +237,93 @@ static int __cam_icp_release_dev_in_ready(struct cam_context *ctx, return rc; } -static int __cam_icp_handle_buf_done_in_ready(void *ctx, - uint32_t evt_id, void *done) +static uint32_t get_error_code(uint32_t err_type) { - return cam_context_buf_done_from_hw(ctx, done, evt_id); + switch (err_type) { + case CAM_ICP_HW_ERROR_NO_MEM: + return CAM_REQ_MGR_ICP_NO_MEMORY; + case CAM_ICP_HW_ERROR_SYSTEM_FAILURE: + return CAM_REQ_MGR_ICP_SYSTEM_FAILURE; + default: + return 0; + } +} + +static int __cam_icp_notify_v4l2_err_evt(struct cam_context *ctx, + uint32_t err_type, uint32_t err_code, uint64_t request_id) +{ + struct cam_req_mgr_message req_msg = {0}; + int rc; + + req_msg.session_hdl = ctx->session_hdl; + req_msg.u.err_msg.device_hdl = ctx->dev_hdl; + req_msg.u.err_msg.error_type = err_type; + req_msg.u.err_msg.link_hdl = ctx->link_hdl; + req_msg.u.err_msg.request_id = request_id; + req_msg.u.err_msg.resource_size = 0x0; + req_msg.u.err_msg.error_code = err_code; + + rc = cam_req_mgr_notify_message(&req_msg, V4L_EVENT_CAM_REQ_MGR_ERROR, + V4L_EVENT_CAM_REQ_MGR_EVENT); + if (rc) + CAM_ERR(CAM_ICP, + "Error in notifying the error time for req id:%lld ctx %u", + request_id, + ctx->ctx_id); + + CAM_INFO(CAM_ICP, + "CTX: [%s][%d] notifying error to userspace err type: %d, err code: %u, req id: %llu", + ctx->dev_name, ctx->ctx_id, err_type, err_code, request_id); + + return rc; +} + +static int cam_icp_ctx_handle_fatal_error(void *ctx, void *err_evt_data) +{ + struct cam_icp_hw_error_evt_data *err_evt; + uint32_t err_code = 0; + int rc; + + err_evt = (struct cam_icp_hw_error_evt_data *)err_evt_data; + err_code = get_error_code(err_evt->err_type); + + rc = __cam_icp_notify_v4l2_err_evt(ctx, CAM_REQ_MGR_ERROR_TYPE_RECOVERY, + err_code, err_evt->req_id); + + return rc; +} + +static int cam_icp_ctx_handle_buf_done_in_ready(void *ctx, void *done_evt_data) +{ + struct cam_icp_hw_buf_done_evt_data *buf_done; + + buf_done = (struct cam_icp_hw_buf_done_evt_data *)done_evt_data; + return cam_context_buf_done_from_hw(ctx, buf_done->buf_done_data, buf_done->evt_id); +} + +static int __cam_icp_ctx_handle_hw_event(void *ctx, + uint32_t evt_id, void *evt_data) +{ + int rc; + + if (!ctx || !evt_data) { + CAM_ERR(CAM_ICP, "Invalid ctx and event data"); + return -EINVAL; + } + + switch (evt_id) { + case CAM_ICP_EVT_ID_BUF_DONE: + rc = cam_icp_ctx_handle_buf_done_in_ready(ctx, evt_data); + break; + case CAM_ICP_EVT_ID_ERROR: + rc = cam_icp_ctx_handle_fatal_error(ctx, evt_data); + break; + default: + CAM_ERR(CAM_ICP, "Invalid event id: %d", evt_id); + rc = -EINVAL; + } + + return rc; } static struct cam_ctx_ops @@ -267,7 +353,7 @@ static struct cam_ctx_ops .dump_dev = __cam_icp_dump_dev_in_ready, }, .crm_ops = {}, - .irq_ops = __cam_icp_handle_buf_done_in_ready, + .irq_ops = __cam_icp_ctx_handle_hw_event, .pagefault_ops = cam_icp_context_dump_active_request, .mini_dump_ops = cam_icp_context_mini_dump, }, @@ -281,7 +367,7 @@ static struct cam_ctx_ops .dump_dev = __cam_icp_dump_dev_in_ready, }, .crm_ops = {}, - .irq_ops = __cam_icp_handle_buf_done_in_ready, + .irq_ops = __cam_icp_ctx_handle_hw_event, .pagefault_ops = cam_icp_context_dump_active_request, .mini_dump_ops = cam_icp_context_mini_dump, }, diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 67b6808f49..9244d5e1e8 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -2105,15 +2105,18 @@ static int cam_icp_mgr_cleanup_ctx(struct cam_icp_hw_ctx_data *ctx_data) { int i; struct hfi_frame_process_info *hfi_frame_process; - struct cam_hw_done_event_data buf_data; + struct cam_icp_hw_buf_done_evt_data icp_evt_data; + struct cam_hw_done_event_data buf_data = {0}; hfi_frame_process = &ctx_data->hfi_frame_process; for (i = 0; i < CAM_FRAME_CMD_MAX; i++) { if (!hfi_frame_process->request_id[i]) continue; buf_data.request_id = hfi_frame_process->request_id[i]; + icp_evt_data.evt_id = CAM_CTX_EVT_ID_SUCCESS; + icp_evt_data.buf_done_data = &buf_data; ctx_data->ctxt_event_cb(ctx_data->context_priv, - CAM_CTX_EVT_ID_SUCCESS, &buf_data); + CAM_ICP_EVT_ID_BUF_DONE, &icp_evt_data); hfi_frame_process->request_id[i] = 0; if (ctx_data->hfi_frame_process.in_resource[i] > 0) { CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", @@ -2141,6 +2144,46 @@ static int cam_icp_mgr_cleanup_ctx(struct cam_icp_hw_ctx_data *ctx_data) return 0; } +static uint32_t cam_icp_handle_err_type_to_evt_param(uint32_t error_type) +{ + switch (error_type) { + case CAMERAICP_ENOMEMORY: + return CAM_SYNC_ICP_EVENT_NO_MEMORY; + case CAMERAICP_EFAILED: + return CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE; + case CAMERAICP_EBADSTATE: + return CAM_SYNC_ICP_EVENT_BAD_STATE; + case CAMERAICP_EBADPARM: + return CAM_SYNC_ICP_EVENT_BAD_PARAM; + case CAMERAICP_EBADITEM: + return CAM_SYNC_ICP_EVENT_BAD_ITEM; + case CAMERAICP_EINVALIDFORMAT: + return CAM_SYNC_ICP_EVENT_INVALID_FORMAT; + case CAMERAICP_EUNSUPPORTED: + return CAM_SYNC_ICP_EVENT_UNSUPPORTED; + case CAMERAICP_EOUTOFBOUND: + return CAM_SYNC_ICP_EVENT_OUT_OF_BOUND; + case CAMERAICP_ETIMEDOUT: + return CAM_SYNC_ICP_EVENT_TIME_OUT; + case CAMERAICP_EABORTED: + return CAM_SYNC_ICP_EVENT_ABORTED; + case CAMERAICP_EHWVIOLATION: + return CAM_SYNC_ICP_EVENT_HW_VIOLATION; + case CAMERAICP_ECDMERROR: + return CAM_SYNC_ICP_EVENT_CMD_ERROR; + case CAMERAICP_HFI_ERR_COMMAND_SIZE: + return CAM_SYNC_ICP_EVENT_HFI_ERR_COMMAND_SIZE; + case CAMERAICP_HFI_ERR_MESSAGE_SIZE: + return CAM_SYNC_ICP_EVENT_HFI_ERR_MESSAGE_SIZE; + case CAMERAICP_HFI_QUEUE_EMPTY: + return CAM_SYNC_ICP_EVENT_HFI_ERR_QUEUE_EMPTY; + case CAMERAICP_HFI_QUEUE_FULL: + return CAM_SYNC_ICP_EVENT_HFI_ERR_QUEUE_FULL; + default: + return CAM_SYNC_ICP_EVENT_UNKNOWN; + } +} + static const char *cam_icp_error_handle_id_to_type( uint32_t error_handle) { @@ -2213,7 +2256,9 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) struct cam_icp_hw_ctx_data *ctx_data = NULL; struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL; struct hfi_frame_process_info *hfi_frame_process; - struct cam_hw_done_event_data buf_data; + struct cam_hw_done_event_data buf_data = {0}; + struct cam_icp_hw_buf_done_evt_data icp_done_evt; + struct cam_icp_hw_error_evt_data icp_err_evt = {0}; uint32_t clk_type; uint32_t event_id; struct cam_hangdump_mem_regions *mem_regions = NULL; @@ -2259,7 +2304,6 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) idx = i; if (flag == ICP_FRAME_PROCESS_FAILURE) { - buf_data.evt_param = CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE; if (ioconfig_ack->err_type == CAMERAICP_EABORTED) { CAM_WARN(CAM_ICP, "ctx_id %d req %llu dev %d has been aborted[flushed]", @@ -2277,6 +2321,7 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) request_id); event_id = CAM_CTX_EVT_ID_ERROR; } + buf_data.evt_param = cam_icp_handle_err_type_to_evt_param(ioconfig_ack->err_type); } else { event_id = CAM_CTX_EVT_ID_SUCCESS; } @@ -2303,7 +2348,11 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) ctx_data->ctx_id_string, hfi_frame_process->request_id[idx], event_id); buf_data.request_id = hfi_frame_process->request_id[idx]; - ctx_data->ctxt_event_cb(ctx_data->context_priv, event_id, &buf_data); + icp_done_evt.evt_id = event_id; + icp_done_evt.buf_done_data = &buf_data; + ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_ICP_EVT_ID_BUF_DONE, + &icp_done_evt); + hfi_frame_process->request_id[idx] = 0; if (ctx_data->hfi_frame_process.in_resource[idx] > 0) { CAM_DBG(CAM_ICP, "Delete merged sync in object: %d", @@ -2313,6 +2362,14 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag) } clear_bit(idx, ctx_data->hfi_frame_process.bitmap); hfi_frame_process->fw_process_flag[idx] = false; + + /* report recovery to userspace if FW encounters no memory */ + if (ioconfig_ack->err_type == CAMERAICP_ENOMEMORY) { + icp_err_evt.err_type = CAM_ICP_HW_ERROR_NO_MEM; + icp_err_evt.req_id = request_id; + ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_ICP_EVT_ID_ERROR, + &icp_err_evt); + } mutex_unlock(&ctx_data->ctx_mutex); return 0; @@ -2609,8 +2666,10 @@ static int cam_icp_ipebps_reset(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr) { - int rc = 0; + int rc = 0, i; struct sfr_buf *sfr_buffer = NULL; + struct cam_icp_hw_ctx_data *ctx_data; + struct cam_icp_hw_error_evt_data icp_err_evt = {0}; CAM_DBG(CAM_ICP, "Enter"); @@ -2627,6 +2686,27 @@ static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr) cam_icp_ipebps_reset(hw_mgr); atomic_set(&hw_mgr->recovery, 1); + + /* Find any active context and notify userspace of system failure */ + icp_err_evt.err_type = CAM_ICP_HW_ERROR_SYSTEM_FAILURE; + mutex_lock(&hw_mgr->hw_mgr_mutex); + for (i = 0; i < CAM_ICP_CTX_MAX; i++) { + ctx_data = &hw_mgr->ctx_data[i]; + mutex_lock(&ctx_data->ctx_mutex); + if (ctx_data->state != CAM_CTX_ACQUIRED) { + mutex_unlock(&ctx_data->ctx_mutex); + continue; + } + ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_ICP_EVT_ID_ERROR, + &icp_err_evt); + mutex_unlock(&ctx_data->ctx_mutex); + break; + } + mutex_unlock(&hw_mgr->hw_mgr_mutex); + if (i == CAM_ICP_CTX_MAX) + CAM_ERR(CAM_ICP, + "Fail to report system failure to userspace due to no active ctx"); + CAM_DBG(CAM_ICP, "Done"); return rc; } @@ -4418,12 +4498,15 @@ static int cam_icp_mgr_handle_config_err( struct cam_icp_hw_ctx_data *ctx_data, int idx) { - struct cam_hw_done_event_data buf_data; + struct cam_icp_hw_buf_done_evt_data icp_evt_data; + struct cam_hw_done_event_data buf_data = {0}; buf_data.request_id = *(uint64_t *)config_args->priv; buf_data.evt_param = CAM_SYNC_ICP_EVENT_CONFIG_ERR; - ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_SUCCESS, - &buf_data); + icp_evt_data.evt_id = CAM_CTX_EVT_ID_ERROR; + icp_evt_data.buf_done_data = &buf_data; + ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_ICP_EVT_ID_BUF_DONE, + &icp_evt_data); ctx_data->hfi_frame_process.request_id[idx] = 0; ctx_data->hfi_frame_process.fw_process_flag[idx] = false; @@ -5573,17 +5656,23 @@ static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv, static int cam_icp_mgr_send_abort_status(struct cam_icp_hw_ctx_data *ctx_data) { struct hfi_frame_process_info *hfi_frame_process; + struct cam_icp_hw_buf_done_evt_data icp_evt_data; + struct cam_hw_done_event_data buf_data = {0}; int idx; mutex_lock(&ctx_data->ctx_mutex); hfi_frame_process = &ctx_data->hfi_frame_process; + buf_data.evt_param = CAM_SYNC_ICP_EVENT_ABORTED; + icp_evt_data.evt_id = CAM_CTX_EVT_ID_CANCEL; for (idx = 0; idx < CAM_FRAME_CMD_MAX; idx++) { if (!hfi_frame_process->request_id[idx]) continue; + buf_data.request_id = hfi_frame_process->request_id[idx]; + icp_evt_data.buf_done_data = &buf_data; ctx_data->ctxt_event_cb(ctx_data->context_priv, - CAM_CTX_EVT_ID_CANCEL, - &hfi_frame_process->request_id[idx]); + CAM_ICP_EVT_ID_BUF_DONE, + &icp_evt_data); /* now release memory for hfi frame process command */ hfi_frame_process->request_id[idx] = 0; @@ -5593,7 +5682,7 @@ static int cam_icp_mgr_send_abort_status(struct cam_icp_hw_ctx_data *ctx_data) cam_sync_destroy( ctx_data->hfi_frame_process.in_resource[idx]); ctx_data->hfi_frame_process.in_resource[idx] = 0; - } + } clear_bit(idx, ctx_data->hfi_frame_process.bitmap); } mutex_unlock(&ctx_data->ctx_mutex); diff --git a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h index 5c40880a9f..276fac1359 100644 --- a/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h +++ b/drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h @@ -31,6 +31,16 @@ #define CAM_ICP_DUMP_TAG_MAX_LEN 64 #define CAM_ICP_DUMP_NUM_WORDS 5 +enum cam_icp_hw_event_type { + CAM_ICP_EVT_ID_BUF_DONE, + CAM_ICP_EVT_ID_ERROR, +}; + +enum cam_icp_hw_error_type { + CAM_ICP_HW_ERROR_NO_MEM, + CAM_ICP_HW_ERROR_SYSTEM_FAILURE, +}; + typedef void(*cam_icp_mini_dump_cb)(void *priv, void *args); @@ -78,4 +88,24 @@ struct cam_icp_dump_header { int32_t word_size; }; +/** + * struct cam_icp_hw_buf_done_evt_data + * @buf_done_data: buf done payload + * @evt_id: event id (success/cancel/error) + */ +struct cam_icp_hw_buf_done_evt_data { + void *buf_done_data; + uint32_t evt_id; +}; + +/** + * struct cam_icp_hw_error_evt_data + * @req_id: request id + * @err_type: type of fatal error + */ +struct cam_icp_hw_error_evt_data { + uint64_t req_id; + enum cam_icp_hw_error_type err_type; +}; + #endif /* CAM_ICP_HW_MGR_INTF_H */ diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index d1c2823ba5..aacbf7b4a9 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -3089,20 +3089,95 @@ static int __cam_isp_ctx_buf_done_in_bubble_applied( return rc; } -static uint32_t get_evt_param(uint32_t error_type) +static void get_notification_evt_params(uint32_t hw_error, uint32_t *fence_evt_cause, + uint32_t *req_mgr_err_code, uint32_t *recovery_type) { - switch (error_type) { - case CAM_ISP_HW_ERROR_OVERFLOW: - return CAM_SYNC_ISP_EVENT_OVERFLOW; - case CAM_ISP_HW_ERROR_P2I_ERROR: - return CAM_SYNC_ISP_EVENT_P2I_ERROR; - case CAM_ISP_HW_ERROR_VIOLATION: - return CAM_SYNC_ISP_EVENT_VIOLATION; - case CAM_ISP_HW_ERROR_BUSIF_OVERFLOW: - return CAM_SYNC_ISP_EVENT_BUSIF_OVERFLOW; - default: - return CAM_SYNC_ISP_EVENT_UNKNOWN; + uint32_t err_type, err_code = 0, recovery_type_temp; + + err_type = CAM_SYNC_ISP_EVENT_UNKNOWN; + recovery_type_temp = CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + + if (hw_error & CAM_ISP_HW_ERROR_OVERFLOW) { + err_code |= CAM_REQ_MGR_ISP_UNREPORTED_ERROR; + err_type = CAM_SYNC_ISP_EVENT_OVERFLOW; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_RECOVERY; } + if (hw_error & CAM_ISP_HW_ERROR_CSID_OUTPUT_FIFO_OVERFLOW) { + err_code |= CAM_REQ_MGR_CSID_FIFO_OVERFLOW_ERROR; + err_type = CAM_SYNC_ISP_EVENT_CSID_OUTPUT_FIFO_OVERFLOW; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_RECOVERY_OVERFLOW) { + err_code |= CAM_REQ_MGR_CSID_RECOVERY_OVERFLOW_ERROR; + err_type = CAM_SYNC_ISP_EVENT_RECOVERY_OVERFLOW; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_P2I_ERROR) { + err_code |= CAM_REQ_MGR_ISP_UNREPORTED_ERROR; + err_type = CAM_SYNC_ISP_EVENT_P2I_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_VIOLATION) { + err_code |= CAM_REQ_MGR_ISP_UNREPORTED_ERROR; + err_type = CAM_SYNC_ISP_EVENT_VIOLATION; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_BUSIF_OVERFLOW) { + err_code |= CAM_REQ_MGR_ISP_UNREPORTED_ERROR; + err_type = CAM_SYNC_ISP_EVENT_BUSIF_OVERFLOW; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_SENSOR_SWITCH_ERROR) { + err_code |= CAM_REQ_MGR_CSID_ERR_ON_SENSOR_SWITCHING; + err_type = CAM_SYNC_ISP_EVENT_CSID_SENSOR_SWITCH_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW) { + err_code |= CAM_REQ_MGR_CSID_LANE_FIFO_OVERFLOW_ERROR; + err_type = CAM_SYNC_ISP_EVENT_CSID_RX_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_PKT_HDR_CORRUPTED) { + err_code |= CAM_REQ_MGR_CSID_RX_PKT_HDR_CORRUPTION; + err_type = CAM_SYNC_ISP_EVENT_CSID_RX_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_MISSING_PKT_HDR_DATA) { + err_code |= CAM_REQ_MGR_CSID_MISSING_PKT_HDR_DATA; + err_type = CAM_SYNC_ISP_EVENT_CSID_RX_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_UNBOUNDED_FRAME) { + err_code |= CAM_REQ_MGR_CSID_UNBOUNDED_FRAME; + err_type = CAM_SYNC_ISP_EVENT_CSID_RX_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_FRAME_SIZE) { + err_code |= CAM_REQ_MGR_CSID_PIXEL_COUNT_MISMATCH; + err_type = CAM_SYNC_ISP_EVENT_CSID_RX_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_MISSING_EOT) { + err_code |= CAM_REQ_MGR_CSID_MISSING_EOT; + err_type = CAM_SYNC_ISP_EVENT_CSID_RX_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + } + if (hw_error & CAM_ISP_HW_ERROR_CSID_PKT_PAYLOAD_CORRUPTED) { + err_code |= CAM_REQ_MGR_CSID_RX_PKT_PAYLOAD_CORRUPTION; + err_type = CAM_SYNC_ISP_EVENT_CSID_RX_ERROR; + recovery_type_temp |= CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + } + + if (recovery_type_temp == (CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY | + CAM_REQ_MGR_ERROR_TYPE_RECOVERY)) + recovery_type_temp = CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; + + if (!err_code) + err_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR; + + *req_mgr_err_code = err_code; + *fence_evt_cause = err_type; + *recovery_type = recovery_type_temp; } static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, @@ -3120,26 +3195,22 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, struct cam_isp_ctx_req *req_isp_to_report = NULL; uint64_t error_request_id; struct cam_hw_fence_map_entry *fence_map_out = NULL; - uint32_t evt_param; + uint32_t recovery_type, fence_evt_cause; + uint32_t req_mgr_err_code; struct cam_context *ctx = ctx_isp->base; struct cam_isp_hw_error_event_data *error_event_data = (struct cam_isp_hw_error_event_data *)evt_data; - uint32_t error_type = error_event_data->error_type; - - CAM_DBG(CAM_ISP, "Enter error_type = %d", error_type); + CAM_DBG(CAM_ISP, "Enter HW error_type = %d", error_event_data->error_type); if (!ctx_isp->offline_context) __cam_isp_ctx_pause_crm_timer(ctx); - if ((error_type == CAM_ISP_HW_ERROR_OVERFLOW) || - (error_type == CAM_ISP_HW_ERROR_BUSIF_OVERFLOW) || - (error_type == CAM_ISP_HW_ERROR_VIOLATION)) - __cam_isp_ctx_trigger_reg_dump(CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR, ctx); - - evt_param = get_evt_param(error_type); + __cam_isp_ctx_trigger_reg_dump(CAM_HW_MGR_CMD_REG_DUMP_ON_ERROR, ctx); + get_notification_evt_params(error_event_data->error_type, &fence_evt_cause, + &req_mgr_err_code, &recovery_type); /* * The error is likely caused by first request on the active list. * If active list is empty check wait list (maybe error hit as soon @@ -3187,7 +3258,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, rc = cam_sync_signal( fence_map_out->sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, - evt_param); + fence_evt_cause); fence_map_out->sync_id = -1; } } @@ -3221,7 +3292,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp, rc = cam_sync_signal( fence_map_out->sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, - evt_param); + fence_evt_cause); fence_map_out->sync_id = -1; } } @@ -3283,7 +3354,7 @@ end: rc = cam_sync_signal( req_isp->fence_map_out[i].sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, - evt_param); + fence_evt_cause); req_isp->fence_map_out[i].sync_id = -1; } list_del_init(&req->list); @@ -3307,16 +3378,9 @@ end: * This will help UMD to take necessary action * and to dump relevant info */ - if (error == CRM_KMD_ERR_FATAL) { - uint32_t req_mgr_error_type = CAM_REQ_MGR_ERROR_TYPE_RECOVERY; - - if (error_type == CAM_ISP_HW_ERROR_CSID_FATAL) - req_mgr_error_type = - CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY; - - __cam_isp_ctx_notify_v4l2_error_event(req_mgr_error_type, - error_event_data->error_code, error_request_id, ctx); - } + if (error == CRM_KMD_ERR_FATAL) + __cam_isp_ctx_notify_v4l2_error_event(recovery_type, + req_mgr_err_code, error_request_id, ctx); ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HW_ERROR; CAM_DBG(CAM_ISP, "Handling error done on ctx: %u", ctx->ctx_id); diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 8e0bb5ce9c..157863ed8d 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -11964,6 +11964,17 @@ static int cam_ife_mgr_recover_hw(void *priv, void *data) switch (error_type) { case CAM_ISP_HW_ERROR_OVERFLOW: + case CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW: + case CAM_ISP_HW_ERROR_CSID_PKT_HDR_CORRUPTED: + case CAM_ISP_HW_ERROR_CSID_MISSING_PKT_HDR_DATA: + case CAM_ISP_HW_ERROR_CSID_SENSOR_SWITCH_ERROR: + case CAM_ISP_HW_ERROR_CSID_FATAL: + case CAM_ISP_HW_ERROR_CSID_UNBOUNDED_FRAME: + case CAM_ISP_HW_ERROR_CSID_MISSING_EOT: + case CAM_ISP_HW_ERROR_CSID_PKT_PAYLOAD_CORRUPTED: + case CAM_ISP_HW_ERROR_CSID_OUTPUT_FIFO_OVERFLOW: + case CAM_ISP_HW_ERROR_RECOVERY_OVERFLOW: + case CAM_ISP_HW_ERROR_CSID_FRAME_SIZE: case CAM_ISP_HW_ERROR_BUSIF_OVERFLOW: case CAM_ISP_HW_ERROR_VIOLATION: if (!recovery_data->affected_ctx[0]) { @@ -12248,6 +12259,8 @@ static int cam_ife_hw_mgr_handle_csid_error( if (err_type & CAM_ISP_HW_ERROR_CSID_SENSOR_FRAME_DROP) cam_ife_hw_mgr_handle_csid_frame_drop(event_info, ctx); + recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; + if ((err_type & (CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW | CAM_ISP_HW_ERROR_CSID_PKT_HDR_CORRUPTED | CAM_ISP_HW_ERROR_CSID_MISSING_PKT_HDR_DATA | @@ -12258,33 +12271,8 @@ static int cam_ife_hw_mgr_handle_csid_error( CAM_ISP_HW_ERROR_CSID_PKT_PAYLOAD_CORRUPTED)) && g_ife_hw_mgr.debug_cfg.enable_csid_recovery) { - error_event_data.error_type = CAM_ISP_HW_ERROR_CSID_FATAL; - - if (err_type & CAM_ISP_HW_ERROR_CSID_SENSOR_SWITCH_ERROR) - error_event_data.error_code |= - CAM_REQ_MGR_CSID_ERR_ON_SENSOR_SWITCHING; - - if (err_type & CAM_ISP_HW_ERROR_CSID_LANE_FIFO_OVERFLOW) - error_event_data.error_code |= CAM_REQ_MGR_CSID_LANE_FIFO_OVERFLOW_ERROR; - - if (err_type & CAM_ISP_HW_ERROR_CSID_PKT_HDR_CORRUPTED) - error_event_data.error_code |= CAM_REQ_MGR_CSID_RX_PKT_HDR_CORRUPTION; - - if (err_type & CAM_ISP_HW_ERROR_CSID_MISSING_PKT_HDR_DATA) - error_event_data.error_code |= CAM_REQ_MGR_CSID_MISSING_PKT_HDR_DATA; - - if (err_type & CAM_ISP_HW_ERROR_CSID_FATAL) - error_event_data.error_code |= CAM_REQ_MGR_ISP_UNREPORTED_ERROR; - - if (err_type & CAM_ISP_HW_ERROR_CSID_UNBOUNDED_FRAME) - error_event_data.error_code |= CAM_REQ_MGR_CSID_UNBOUNDED_FRAME; - - if (err_type & CAM_ISP_HW_ERROR_CSID_MISSING_EOT) - error_event_data.error_code |= CAM_REQ_MGR_CSID_MISSING_EOT; - - if (err_type & CAM_ISP_HW_ERROR_CSID_PKT_PAYLOAD_CORRUPTED) - error_event_data.error_code |= CAM_REQ_MGR_CSID_RX_PKT_PAYLOAD_CORRUPTION; - + error_event_data.error_type |= err_type; + recovery_data.error_type = err_type; rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data, event_info->hw_idx, &recovery_data); goto end; @@ -12295,16 +12283,9 @@ static int cam_ife_hw_mgr_handle_csid_error( CAM_ISP_HW_ERROR_CSID_FRAME_SIZE)) { cam_ife_hw_mgr_notify_overflow(event_info, ctx); - error_event_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; - if (err_type & CAM_ISP_HW_ERROR_CSID_OUTPUT_FIFO_OVERFLOW) - error_event_data.error_code |= CAM_REQ_MGR_CSID_FIFO_OVERFLOW_ERROR; - - if (err_type & CAM_ISP_HW_ERROR_RECOVERY_OVERFLOW) - error_event_data.error_code |= CAM_REQ_MGR_CSID_RECOVERY_OVERFLOW_ERROR; - - if (err_type & CAM_ISP_HW_ERROR_CSID_FRAME_SIZE) - error_event_data.error_code |= CAM_REQ_MGR_CSID_PIXEL_COUNT_MISMATCH; + error_event_data.error_type |= err_type; + recovery_data.error_type = err_type; rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data, event_info->hw_idx, &recovery_data); } @@ -12314,7 +12295,6 @@ end: if (rc || !recovery_data.no_of_context) goto skip_recovery; - recovery_data.error_type = CAM_ISP_HW_ERROR_OVERFLOW; cam_ife_hw_mgr_do_error_recovery(&recovery_data); CAM_DBG(CAM_ISP, "Exit CSID[%u] error %d", event_info->hw_idx, err_type); @@ -12506,7 +12486,6 @@ static int cam_ife_hw_mgr_handle_sfe_hw_error( /* Only report error to userspace */ if (err_evt_info->err_type & CAM_SFE_IRQ_STATUS_VIOLATION) { error_event_data.error_type = CAM_ISP_HW_ERROR_VIOLATION; - error_event_data.error_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR; CAM_DBG(CAM_ISP, "Notify context for SFE error"); cam_ife_hw_mgr_find_affected_ctx(&error_event_data, event_info->hw_idx, &recovery_data); @@ -12559,8 +12538,6 @@ static int cam_ife_hw_mgr_handle_hw_err( if (g_ife_hw_mgr.debug_cfg.enable_req_dump) error_event_data.enable_req_dump = true; - error_event_data.error_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR; - rc = cam_ife_hw_mgr_find_affected_ctx(&error_event_data, core_idx, &recovery_data); diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 3ab4b6b86e..bada5392a9 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_ISP_HW_MGR_INTF_H_ @@ -326,8 +327,7 @@ struct cam_isp_hw_eof_event_data { /** * struct cam_isp_hw_error_event_data - Event payload for CAM_HW_EVENT_ERROR * - * @error_type: Error type for the error event - * @error_code: HW Error Code that caused to trigger this event + * @error_type: HW error type for the error event * @timestamp: Timestamp for the error event * @recovery_enabled: Identifies if the context needs to recover & reapply * this request @@ -335,7 +335,6 @@ struct cam_isp_hw_eof_event_data { */ struct cam_isp_hw_error_event_data { uint32_t error_type; - uint32_t error_code; uint64_t timestamp; bool recovery_enabled; bool enable_req_dump;