Loading drivers/cam_cust/cam_custom_context.c +157 −25 Original line number Diff line number Diff line Loading @@ -181,11 +181,28 @@ static int __cam_custom_ctx_frame_done( continue; } rc = cam_sync_signal(req_custom->fence_map_out[j].sync_id, if (!req_custom->bubble_detected) { rc = cam_sync_signal( req_custom->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS, CAM_SYNC_COMMON_EVENT_SUCCESS); if (rc) CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); } else if (!req_custom->bubble_report) { rc = cam_sync_signal( req_custom->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, CAM_SYNC_ISP_EVENT_BUBBLE); if (rc) CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); } else { req_custom->num_acked++; CAM_DBG(CAM_CUSTOM, "frame done with bubble for %llu", req->request_id); continue; } req_custom->num_acked++; req_custom->fence_map_out[j].sync_id = -1; Loading @@ -203,15 +220,131 @@ static int __cam_custom_ctx_frame_done( custom_ctx->active_req_cnt--; frame_done_req_id = req->request_id; if (req_custom->bubble_detected && req_custom->bubble_report) { req_custom->num_acked = 0; req_custom->bubble_detected = false; list_del_init(&req->list); if (frame_done_req_id <= ctx->last_flush_req) { for (i = 0; i < req_custom->num_fence_map_out; i++) rc = cam_sync_signal( req_custom->fence_map_out[i].sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, CAM_SYNC_ISP_EVENT_BUBBLE); list_add_tail(&req->list, &ctx->free_req_list); atomic_set(&custom_ctx->process_bubble, 0); CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); } else { list_add(&req->list, &ctx->pending_req_list); atomic_set(&custom_ctx->process_bubble, 0); CAM_DBG(CAM_REQ, "Move active request %lld to pending list in ctx %u", frame_done_req_id, ctx->ctx_id); } } else { list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); } return rc; } static int __cam_custom_ctx_handle_bubble( struct cam_context *ctx, uint64_t req_id) { int rc = -EINVAL; bool found = false; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp; struct cam_custom_dev_ctx_req *req_custom; list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) { if (req->request_id == req_id) { req_custom = (struct cam_custom_dev_ctx_req *)req->req_priv; if (!req_custom->bubble_report) { CAM_DBG(CAM_CUSTOM, "Skip bubble recovery for %llu", req_id); goto end; } req_custom->bubble_detected = true; found = true; CAM_DBG(CAM_CUSTOM, "Found bubbled req %llu in wait list", req_id); } } if (found) { rc = 0; goto end; } list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) { if (req->request_id == req_id) { req_custom = (struct cam_custom_dev_ctx_req *)req->req_priv; if (!req_custom->bubble_report) { CAM_DBG(CAM_CUSTOM, "Skip bubble recovery for %llu", req_id); goto end; } req_custom->bubble_detected = true; found = true; CAM_DBG(CAM_CUSTOM, "Found bubbled req %llu in active list", req_id); } } if (found) rc = 0; else CAM_ERR(CAM_CUSTOM, "req %llu not found in wait or active list bubble recovery failed ctx: %u", req_id, ctx->ctx_id); end: return rc; } static int __cam_custom_ctx_handle_evt( struct cam_context *ctx, struct cam_req_mgr_link_evt_data *evt_data) { int rc = -1; struct cam_custom_context *custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; if (evt_data->u.error == CRM_KMD_ERR_BUBBLE) { rc = __cam_custom_ctx_handle_bubble(ctx, evt_data->req_id); if (rc) return rc; } else { CAM_WARN(CAM_CUSTOM, "Unsupported error type %d", evt_data->u.error); } CAM_DBG(CAM_CUSTOM, "Set bubble flag for req %llu in ctx %u", evt_data->req_id, ctx->ctx_id); atomic_set(&custom_ctx->process_bubble, 1); return 0; } static struct cam_ctx_ops cam_custom_ctx_activated_state_machine [CAM_CUSTOM_CTX_ACTIVATED_MAX] = { Loading Loading @@ -487,6 +620,7 @@ static int __cam_custom_ctx_flush_req_in_top_state( } end: atomic_set(&custom_ctx->process_bubble, 0); return rc; } Loading @@ -495,6 +629,8 @@ static int __cam_custom_ctx_flush_req_in_ready( struct cam_req_mgr_flush_request *flush_req) { int rc = 0; struct cam_custom_context *custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; CAM_DBG(CAM_CUSTOM, "try to flush pending list"); spin_lock_bh(&ctx->lock); Loading @@ -505,6 +641,7 @@ static int __cam_custom_ctx_flush_req_in_ready( ctx->state = CAM_CTX_ACQUIRED; spin_unlock_bh(&ctx->lock); atomic_set(&custom_ctx->process_bubble, 0); CAM_DBG(CAM_CUSTOM, "Flush request in ready state. next state %d", ctx->state); return rc; Loading Loading @@ -751,6 +888,14 @@ static int __cam_custom_ctx_apply_req_in_activated_state( struct cam_custom_context *custom_ctx = NULL; struct cam_hw_config_args cfg; if (atomic_read(&custom_ctx->process_bubble)) { CAM_WARN(CAM_CUSTOM, "ctx_id:%d Processing bubble cannot apply Request Id %llu", ctx->ctx_id, apply->request_id); rc = -EAGAIN; goto end; } if (list_empty(&ctx->pending_req_list)) { CAM_ERR(CAM_CUSTOM, "No available request for Apply id %lld", apply->request_id); Loading Loading @@ -779,7 +924,7 @@ static int __cam_custom_ctx_apply_req_in_activated_state( } req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; req_custom->bubble_report = apply->report_if_bubble; cfg.ctxt_to_hw_map = custom_ctx->hw_ctx; cfg.request_id = req->request_id; cfg.hw_update_entries = req_custom->cfg; Loading Loading @@ -1287,6 +1432,7 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, ctx_custom->frame_id = 0; ctx_custom->active_req_cnt = 0; atomic_set(&ctx_custom->process_bubble, 0); ctx_custom->substate_activated = (req_custom->num_fence_map_out) ? CAM_CUSTOM_CTX_ACTIVATED_APPLIED : Loading Loading @@ -1349,21 +1495,6 @@ static int __cam_custom_ctx_unlink_in_activated(struct cam_context *ctx, return rc; } static int __cam_custom_ctx_process_evt(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *link_evt_data) { switch (link_evt_data->evt_type) { case CAM_REQ_MGR_LINK_EVT_ERR: /* Handle error/bubble related issues */ break; default: CAM_WARN(CAM_CUSTOM, "Unknown event from CRM"); break; } return 0; } static int __cam_custom_ctx_handle_irq_in_activated(void *context, uint32_t evt_id, void *evt_data) { Loading Loading @@ -1537,6 +1668,7 @@ static struct cam_ctx_ops }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, .process_evt = __cam_custom_ctx_handle_evt, }, .irq_ops = NULL, }, Loading @@ -1556,7 +1688,7 @@ static struct cam_ctx_ops .notify_frame_skip = __cam_custom_ctx_apply_default_req, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, .process_evt = __cam_custom_ctx_handle_evt, }, .irq_ops = __cam_custom_ctx_handle_irq_in_activated, .pagefault_ops = NULL, Loading drivers/cam_cust/cam_custom_context.h +7 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only * * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CUSTOM_CONTEXT_H_ Loading Loading @@ -65,6 +65,8 @@ struct cam_custom_ctx_irq_ops { * @num_acked: Count to track acked entried for output. * If count equals the number of fence out, it means * the request has been completed. * @bubble_report: If bubble recovery is needed * @bubble_detected: request has bubbled * @hw_update_data: HW update data for this request * */ Loading @@ -80,6 +82,8 @@ struct cam_custom_dev_ctx_req { [CAM_CUSTOM_DEV_CTX_RES_MAX]; uint32_t num_fence_map_in; uint32_t num_acked; int32_t bubble_report; bool bubble_detected; struct cam_custom_prepare_hw_update_data hw_update_data; }; Loading @@ -95,6 +99,7 @@ struct cam_custom_dev_ctx_req { * @active_req_cnt: Counter for the active request * @frame_id: Frame id tracking for the custom context * @hw_acquired: Flag to indicate if HW is acquired for this context * @process_bubble: If ctx currently processing bubble * @substate_actiavted: Current substate for the activated state. * @substate_machine: Custom substate machine for external interface * @substate_machine_irq: Custom substate machine for irq handling Loading @@ -113,6 +118,7 @@ struct cam_custom_context { int64_t frame_id; bool hw_acquired; uint32_t substate_activated; atomic_t process_bubble; struct cam_ctx_ops *substate_machine; struct cam_custom_ctx_irq_ops *substate_machine_irq; struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; Loading Loading
drivers/cam_cust/cam_custom_context.c +157 −25 Original line number Diff line number Diff line Loading @@ -181,11 +181,28 @@ static int __cam_custom_ctx_frame_done( continue; } rc = cam_sync_signal(req_custom->fence_map_out[j].sync_id, if (!req_custom->bubble_detected) { rc = cam_sync_signal( req_custom->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_SUCCESS, CAM_SYNC_COMMON_EVENT_SUCCESS); if (rc) CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); } else if (!req_custom->bubble_report) { rc = cam_sync_signal( req_custom->fence_map_out[j].sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, CAM_SYNC_ISP_EVENT_BUBBLE); if (rc) CAM_ERR(CAM_CUSTOM, "Sync failed with rc = %d", rc); } else { req_custom->num_acked++; CAM_DBG(CAM_CUSTOM, "frame done with bubble for %llu", req->request_id); continue; } req_custom->num_acked++; req_custom->fence_map_out[j].sync_id = -1; Loading @@ -203,15 +220,131 @@ static int __cam_custom_ctx_frame_done( custom_ctx->active_req_cnt--; frame_done_req_id = req->request_id; if (req_custom->bubble_detected && req_custom->bubble_report) { req_custom->num_acked = 0; req_custom->bubble_detected = false; list_del_init(&req->list); if (frame_done_req_id <= ctx->last_flush_req) { for (i = 0; i < req_custom->num_fence_map_out; i++) rc = cam_sync_signal( req_custom->fence_map_out[i].sync_id, CAM_SYNC_STATE_SIGNALED_ERROR, CAM_SYNC_ISP_EVENT_BUBBLE); list_add_tail(&req->list, &ctx->free_req_list); atomic_set(&custom_ctx->process_bubble, 0); CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [flushed], ctx %u", frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); } else { list_add(&req->list, &ctx->pending_req_list); atomic_set(&custom_ctx->process_bubble, 0); CAM_DBG(CAM_REQ, "Move active request %lld to pending list in ctx %u", frame_done_req_id, ctx->ctx_id); } } else { list_del_init(&req->list); list_add_tail(&req->list, &ctx->free_req_list); CAM_DBG(CAM_REQ, "Move active request %lld to free list(cnt = %d) [all fences done], ctx %u", frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); frame_done_req_id, custom_ctx->active_req_cnt, ctx->ctx_id); } return rc; } static int __cam_custom_ctx_handle_bubble( struct cam_context *ctx, uint64_t req_id) { int rc = -EINVAL; bool found = false; struct cam_ctx_request *req = NULL; struct cam_ctx_request *req_temp; struct cam_custom_dev_ctx_req *req_custom; list_for_each_entry_safe(req, req_temp, &ctx->wait_req_list, list) { if (req->request_id == req_id) { req_custom = (struct cam_custom_dev_ctx_req *)req->req_priv; if (!req_custom->bubble_report) { CAM_DBG(CAM_CUSTOM, "Skip bubble recovery for %llu", req_id); goto end; } req_custom->bubble_detected = true; found = true; CAM_DBG(CAM_CUSTOM, "Found bubbled req %llu in wait list", req_id); } } if (found) { rc = 0; goto end; } list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) { if (req->request_id == req_id) { req_custom = (struct cam_custom_dev_ctx_req *)req->req_priv; if (!req_custom->bubble_report) { CAM_DBG(CAM_CUSTOM, "Skip bubble recovery for %llu", req_id); goto end; } req_custom->bubble_detected = true; found = true; CAM_DBG(CAM_CUSTOM, "Found bubbled req %llu in active list", req_id); } } if (found) rc = 0; else CAM_ERR(CAM_CUSTOM, "req %llu not found in wait or active list bubble recovery failed ctx: %u", req_id, ctx->ctx_id); end: return rc; } static int __cam_custom_ctx_handle_evt( struct cam_context *ctx, struct cam_req_mgr_link_evt_data *evt_data) { int rc = -1; struct cam_custom_context *custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; if (evt_data->u.error == CRM_KMD_ERR_BUBBLE) { rc = __cam_custom_ctx_handle_bubble(ctx, evt_data->req_id); if (rc) return rc; } else { CAM_WARN(CAM_CUSTOM, "Unsupported error type %d", evt_data->u.error); } CAM_DBG(CAM_CUSTOM, "Set bubble flag for req %llu in ctx %u", evt_data->req_id, ctx->ctx_id); atomic_set(&custom_ctx->process_bubble, 1); return 0; } static struct cam_ctx_ops cam_custom_ctx_activated_state_machine [CAM_CUSTOM_CTX_ACTIVATED_MAX] = { Loading Loading @@ -487,6 +620,7 @@ static int __cam_custom_ctx_flush_req_in_top_state( } end: atomic_set(&custom_ctx->process_bubble, 0); return rc; } Loading @@ -495,6 +629,8 @@ static int __cam_custom_ctx_flush_req_in_ready( struct cam_req_mgr_flush_request *flush_req) { int rc = 0; struct cam_custom_context *custom_ctx = (struct cam_custom_context *) ctx->ctx_priv; CAM_DBG(CAM_CUSTOM, "try to flush pending list"); spin_lock_bh(&ctx->lock); Loading @@ -505,6 +641,7 @@ static int __cam_custom_ctx_flush_req_in_ready( ctx->state = CAM_CTX_ACQUIRED; spin_unlock_bh(&ctx->lock); atomic_set(&custom_ctx->process_bubble, 0); CAM_DBG(CAM_CUSTOM, "Flush request in ready state. next state %d", ctx->state); return rc; Loading Loading @@ -751,6 +888,14 @@ static int __cam_custom_ctx_apply_req_in_activated_state( struct cam_custom_context *custom_ctx = NULL; struct cam_hw_config_args cfg; if (atomic_read(&custom_ctx->process_bubble)) { CAM_WARN(CAM_CUSTOM, "ctx_id:%d Processing bubble cannot apply Request Id %llu", ctx->ctx_id, apply->request_id); rc = -EAGAIN; goto end; } if (list_empty(&ctx->pending_req_list)) { CAM_ERR(CAM_CUSTOM, "No available request for Apply id %lld", apply->request_id); Loading Loading @@ -779,7 +924,7 @@ static int __cam_custom_ctx_apply_req_in_activated_state( } req_custom = (struct cam_custom_dev_ctx_req *) req->req_priv; req_custom->bubble_report = apply->report_if_bubble; cfg.ctxt_to_hw_map = custom_ctx->hw_ctx; cfg.request_id = req->request_id; cfg.hw_update_entries = req_custom->cfg; Loading Loading @@ -1287,6 +1432,7 @@ static int __cam_custom_ctx_start_dev_in_ready(struct cam_context *ctx, ctx_custom->frame_id = 0; ctx_custom->active_req_cnt = 0; atomic_set(&ctx_custom->process_bubble, 0); ctx_custom->substate_activated = (req_custom->num_fence_map_out) ? CAM_CUSTOM_CTX_ACTIVATED_APPLIED : Loading Loading @@ -1349,21 +1495,6 @@ static int __cam_custom_ctx_unlink_in_activated(struct cam_context *ctx, return rc; } static int __cam_custom_ctx_process_evt(struct cam_context *ctx, struct cam_req_mgr_link_evt_data *link_evt_data) { switch (link_evt_data->evt_type) { case CAM_REQ_MGR_LINK_EVT_ERR: /* Handle error/bubble related issues */ break; default: CAM_WARN(CAM_CUSTOM, "Unknown event from CRM"); break; } return 0; } static int __cam_custom_ctx_handle_irq_in_activated(void *context, uint32_t evt_id, void *evt_data) { Loading Loading @@ -1537,6 +1668,7 @@ static struct cam_ctx_ops }, .crm_ops = { .unlink = __cam_custom_ctx_unlink_in_ready, .process_evt = __cam_custom_ctx_handle_evt, }, .irq_ops = NULL, }, Loading @@ -1556,7 +1688,7 @@ static struct cam_ctx_ops .notify_frame_skip = __cam_custom_ctx_apply_default_req, .flush_req = __cam_custom_ctx_flush_req_in_top_state, .process_evt = __cam_custom_ctx_process_evt, .process_evt = __cam_custom_ctx_handle_evt, }, .irq_ops = __cam_custom_ctx_handle_irq_in_activated, .pagefault_ops = NULL, Loading
drivers/cam_cust/cam_custom_context.h +7 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only * * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CUSTOM_CONTEXT_H_ Loading Loading @@ -65,6 +65,8 @@ struct cam_custom_ctx_irq_ops { * @num_acked: Count to track acked entried for output. * If count equals the number of fence out, it means * the request has been completed. * @bubble_report: If bubble recovery is needed * @bubble_detected: request has bubbled * @hw_update_data: HW update data for this request * */ Loading @@ -80,6 +82,8 @@ struct cam_custom_dev_ctx_req { [CAM_CUSTOM_DEV_CTX_RES_MAX]; uint32_t num_fence_map_in; uint32_t num_acked; int32_t bubble_report; bool bubble_detected; struct cam_custom_prepare_hw_update_data hw_update_data; }; Loading @@ -95,6 +99,7 @@ struct cam_custom_dev_ctx_req { * @active_req_cnt: Counter for the active request * @frame_id: Frame id tracking for the custom context * @hw_acquired: Flag to indicate if HW is acquired for this context * @process_bubble: If ctx currently processing bubble * @substate_actiavted: Current substate for the activated state. * @substate_machine: Custom substate machine for external interface * @substate_machine_irq: Custom substate machine for irq handling Loading @@ -113,6 +118,7 @@ struct cam_custom_context { int64_t frame_id; bool hw_acquired; uint32_t substate_activated; atomic_t process_bubble; struct cam_ctx_ops *substate_machine; struct cam_custom_ctx_irq_ops *substate_machine_irq; struct cam_ctx_request req_base[CAM_CTX_REQ_MAX]; Loading