diff --git a/drivers/cam_cust/cam_custom_context.c b/drivers/cam_cust/cam_custom_context.c index 654e2ff6cc..f9098e791e 100644 --- a/drivers/cam_cust/cam_custom_context.c +++ b/drivers/cam_cust/cam_custom_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -1266,10 +1266,10 @@ static int __cam_custom_ctx_config_dev(struct cam_context *ctx, if ((ctx->state != CAM_CTX_FLUSHED) && (ctx->state >= CAM_CTX_READY) && (ctx->ctx_crm_intf->add_req)) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; - add_req.skip_before_applying = 0; rc = ctx->ctx_crm_intf->add_req(&add_req); if (rc) { CAM_ERR(CAM_CUSTOM, @@ -1375,7 +1375,6 @@ static int __cam_custom_ctx_link_in_acquired(struct cam_context *ctx, ctx->link_hdl = link->link_hdl; ctx->ctx_crm_intf = link->crm_cb; - ctx_custom->subscribe_event = link->subscribe_event; /* change state only if we had the init config */ if (ctx_custom->init_received) diff --git a/drivers/cam_cust/cam_custom_context.h b/drivers/cam_cust/cam_custom_context.h index b352d3a374..ef7fe1f874 100644 --- a/drivers/cam_cust/cam_custom_context.h +++ b/drivers/cam_cust/cam_custom_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only * - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CUSTOM_CONTEXT_H_ @@ -94,8 +94,6 @@ struct cam_custom_dev_ctx_req { * @state: Common context state * @hw_ctx: HW object returned by the acquire device command * @init_received: Indicate whether init config packet is received - * @subscribe_event: The irq event mask that CRM subscribes to, - * custom HW will invoke CRM cb at those event. * @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 @@ -113,7 +111,6 @@ struct cam_custom_context { uint32_t state; void *hw_ctx; bool init_received; - uint32_t subscribe_event; uint32_t active_req_cnt; int64_t frame_id; bool hw_acquired; diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 6b257b4783..c0488ce025 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -4608,11 +4608,10 @@ static int __cam_isp_ctx_config_dev_in_top_state( } else if ((ctx->state != CAM_CTX_FLUSHED) && (ctx->state >= CAM_CTX_READY) && ctx->ctx_crm_intf->add_req) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = ctx->link_hdl; add_req.dev_hdl = ctx->dev_hdl; add_req.req_id = req->request_id; - add_req.skip_before_applying = 0; - add_req.trigger_eof = false; rc = ctx->ctx_crm_intf->add_req(&add_req); if (rc) { CAM_ERR(CAM_ISP, "Add req failed: req id=%llu", diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index 46532aa4b8..1642b5a44a 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/cam_req_mgr/cam_req_mgr_core.c @@ -38,15 +38,15 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->watchdog = NULL; link->state = CAM_CRM_LINK_STATE_AVAILABLE; link->parent = NULL; - link->subscribe_event = 0; - link->trigger_mask = 0; link->sync_link_sof_skip = false; link->open_req_cnt = 0; link->last_flush_id = 0; link->initial_sync_req = -1; link->dual_trigger = false; - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; + link->trigger_cnt[0][0] = 0; + link->trigger_cnt[0][1] = 0; + link->trigger_cnt[1][0] = 0; + link->trigger_cnt[1][1] = 0; link->in_msync_mode = false; link->retry_cnt = 0; link->is_shutdown = false; @@ -162,25 +162,34 @@ static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val) /** * __cam_req_mgr_inject_delay() * - * @brief : Check if any pd device is injecting delay - * @tbl : cam_req_mgr_req_tbl - * @curr_idx : slot idx + * @brief : Check if any pd device is injecting delay + * @tbl : cam_req_mgr_req_tbl + * @curr_idx : slot idx + * @trigger : Trigger point * * @return : 0 for success, negative for failure */ static int __cam_req_mgr_inject_delay( - struct cam_req_mgr_req_tbl *tbl, - int32_t curr_idx) + struct cam_req_mgr_req_tbl *tbl, + int32_t curr_idx, uint32_t trigger) { struct cam_req_mgr_tbl_slot *slot = NULL; int rc = 0; while (tbl) { slot = &tbl->slot[curr_idx]; - if (slot->inject_delay > 0) { - slot->inject_delay--; + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (slot->inject_delay_at_sof > 0)) { + slot->inject_delay_at_sof--; CAM_DBG(CAM_CRM, - "Delay injected by pd %d device", + "Delay injected by pd %d device at SOF", + tbl->pd); + rc = -EAGAIN; + } else if ((trigger == CAM_TRIGGER_POINT_EOF) && + (slot->inject_delay_at_eof > 0)) { + slot->inject_delay_at_eof--; + CAM_DBG(CAM_CRM, + "Delay injected by pd %d device at EOF", tbl->pd); rc = -EAGAIN; } @@ -557,7 +566,6 @@ static void __cam_req_mgr_flush_req_slot( tbl->slot[idx].req_ready_map = 0; tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; tbl->slot[idx].ops.apply_at_eof = false; - tbl->slot[idx].ops.skip_next_frame = false; tbl->slot[idx].ops.dev_hdl = -1; tbl->slot[idx].ops.is_applied = false; tbl = tbl->next; @@ -567,10 +575,10 @@ static void __cam_req_mgr_flush_req_slot( atomic_set(&link->eof_event_cnt, 0); in_q->wr_idx = 0; in_q->rd_idx = 0; - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; - link->trigger_mask = 0; - link->subscribe_event &= ~CAM_TRIGGER_POINT_EOF; + link->trigger_cnt[0][0] = 0; + link->trigger_cnt[0][1] = 0; + link->trigger_cnt[1][0] = 0; + link->trigger_cnt[1][1] = 0; } /** @@ -611,8 +619,9 @@ static void __cam_req_mgr_reset_req_slot(struct cam_req_mgr_core_link *link, tbl->pd, idx, tbl->slot[idx].state); tbl->slot[idx].req_ready_map = 0; tbl->slot[idx].state = CRM_REQ_STATE_EMPTY; + tbl->slot[idx].inject_delay_at_sof = 0; + tbl->slot[idx].inject_delay_at_eof = 0; tbl->slot[idx].ops.apply_at_eof = false; - tbl->slot[idx].ops.skip_next_frame = false; tbl->slot[idx].ops.dev_hdl = -1; tbl->slot[idx].ops.is_applied = false; tbl = tbl->next; @@ -820,7 +829,8 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, if (slot->ops.dev_hdl < 0) { CAM_DBG(CAM_CRM, - "No special ops detected for this table slot"); + "No special ops detected for slot %d dev %s", + idx, dev->dev_info.name); continue; } @@ -831,6 +841,23 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, continue; } + if (apply_data[pd].skip_idx || + (apply_data[pd].req_id < 0)) { + CAM_DBG(CAM_CRM, + "dev %s skip %d req_id %lld", + dev->dev_info.name, + apply_data[pd].skip_idx, + apply_data[pd].req_id); + apply_req.dev_hdl = dev->dev_hdl; + apply_req.request_id = + link->req.prev_apply_data[pd].req_id; + apply_req.trigger_point = 0; + apply_req.report_if_bubble = 0; + if ((dev->ops) && (dev->ops->notify_frame_skip)) + dev->ops->notify_frame_skip(&apply_req); + continue; + } + /* This one is to prevent EOF request to apply on SOF*/ if ((trigger == CAM_TRIGGER_POINT_SOF) && (slot->ops.apply_at_eof)) { @@ -858,31 +885,24 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, trigger); return rc; } + } else { + CAM_DBG(CAM_REQ, + "link_hdl: %x pd: %d req_id %lld has applied", + link->link_hdl, pd, apply_req.request_id); + break; } CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd: %d req_id %lld", - link->link_hdl, pd, apply_req.request_id); + "SEND: link_hdl %x dev %s pd %d req_id %lld", + link->link_hdl, dev->dev_info.name, + pd, apply_req.request_id); - if (trigger == CAM_TRIGGER_POINT_SOF && - slot->ops.skip_next_frame) { - slot->ops.skip_next_frame = false; - slot->ops.is_applied = true; - CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd: %d req_id %lld", - link->link_hdl, pd, apply_req.request_id); - __cam_req_mgr_notify_frame_skip(link, - trigger); - return -EAGAIN; - } else if ((trigger == CAM_TRIGGER_POINT_EOF) && + if ((trigger == CAM_TRIGGER_POINT_EOF) && (slot->ops.apply_at_eof)) { + slot->ops.is_applied = true; slot->ops.apply_at_eof = false; if (atomic_read(&link->eof_event_cnt) > 0) atomic_dec(&link->eof_event_cnt); - CAM_DBG(CAM_REQ, - "Req_id: %llu eof_event_cnt : %d", - apply_data[pd].req_id, - link->eof_event_cnt); return 0; } } @@ -964,8 +984,9 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, apply_req.trigger_point = trigger; CAM_DBG(CAM_REQ, - "SEND: link_hdl: %x pd %d req_id %lld", - link->link_hdl, pd, apply_req.request_id); + "SEND: link_hdl %x dev %s pd %d req_id %lld", + link->link_hdl, dev->dev_info.name, + pd, apply_req.request_id); if (dev->ops && dev->ops->apply_req) { rc = dev->ops->apply_req(&apply_req); if (rc < 0) { @@ -1163,7 +1184,6 @@ static int __cam_req_mgr_check_sync_for_mslave( "No req applied on corresponding SOF on sync link: %x", sync_link->link_hdl); sync_link->sync_link_sof_skip = false; - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); return -EAGAIN; } @@ -1181,15 +1201,6 @@ static int __cam_req_mgr_check_sync_for_mslave( } if (link->is_master) { - rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); - if (rc) { - CAM_DBG(CAM_CRM, - "Skip Process Req: %lld on link: %x", - req_id, link->link_hdl); - link->sync_link_sof_skip = true; - return rc; - } - if (sync_link->initial_skip) { CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", sync_link->link_hdl); @@ -1253,15 +1264,6 @@ static int __cam_req_mgr_check_sync_for_mslave( if (link->initial_skip) link->initial_skip = false; - rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); - if (rc) { - CAM_DBG(CAM_CRM, - "Skip Process Req: %lld on link: %x", - req_id, link->link_hdl); - link->sync_link_sof_skip = true; - return rc; - } - rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); if (rc) { CAM_DBG(CAM_CRM, @@ -1374,7 +1376,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( if (sync_link->initial_skip) { link->initial_skip = false; - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); CAM_DBG(CAM_CRM, "sync link %x not streamed on", sync_link->link_hdl); @@ -1408,7 +1409,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( * link, then we need to skip this frame, since the * previous frame of sync link is also skipped. */ - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); CAM_DBG(CAM_CRM, "This frame sync with previous sync_link %x frame", sync_link->link_hdl); @@ -1421,7 +1421,6 @@ static int __cam_req_mgr_check_sync_req_is_ready( * we need to skip this SOF event since the sync * link's SOF event is also skipped. */ - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); CAM_DBG(CAM_CRM, "The previous frame of sync link is skipped"); return -EAGAIN; @@ -1433,18 +1432,9 @@ static int __cam_req_mgr_check_sync_req_is_ready( "No req applied on corresponding SOF on sync link: %x", sync_link->link_hdl); sync_link->sync_link_sof_skip = false; - __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); return -EAGAIN; } - rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); - if (rc) { - CAM_DBG(CAM_CRM, - "Skip Process Req: %lld on link: %x", - req_id, link->link_hdl); - ready = false; - } - sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, req_id); if (sync_slot_idx == -1) { @@ -1564,7 +1554,8 @@ static int __cam_req_mgr_check_sync_req_is_ready( static int __cam_req_mgr_check_multi_sync_link_ready( struct cam_req_mgr_core_link *link, - struct cam_req_mgr_slot *slot) + struct cam_req_mgr_slot *slot, + uint32_t trigger) { int i, rc = 0; @@ -1618,6 +1609,16 @@ static int __cam_req_mgr_check_multi_sync_link_ready( } } + rc = __cam_req_mgr_inject_delay(link->req.l_tbl, + slot->idx, trigger); + if (rc < 0) { + CAM_DBG(CAM_CRM, + "Req: %lld needs to inject delay at %s", + slot->req_id, + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"); + return -EINVAL; + } + /* * At this point all validation is successfully done * and we can proceed to apply the given request. @@ -1630,6 +1631,57 @@ static int __cam_req_mgr_check_multi_sync_link_ready( return 0; } +/** + * __cam_req_mgr_check_for_eof() + * + * @brief : Checks for eof trigger type + * @link : pointer to link whose input queue and req tbl are + * traversed through + * + * @return : eof trigger type + * + */ +enum crm_req_eof_trigger_type __cam_req_mgr_check_for_eof( + struct cam_req_mgr_core_link *link) +{ + int32_t curr_idx; + struct cam_req_mgr_req_queue *in_q; + enum crm_req_eof_trigger_type eof_trigger_type; + struct cam_req_mgr_tbl_slot *slot = NULL; + struct cam_req_mgr_req_tbl *tbl; + + in_q = link->req.in_q; + tbl = link->req.l_tbl; + curr_idx = in_q->rd_idx; + eof_trigger_type = CAM_REQ_EOF_TRIGGER_NONE; + + while (tbl != NULL) { + slot = &tbl->slot[curr_idx]; + + if (slot->ops.is_applied) { + eof_trigger_type = CAM_REQ_EOF_TRIGGER_APPLIED; + break; + } else if (slot->ops.apply_at_eof) { + eof_trigger_type = CAM_REQ_EOF_TRIGGER_NOT_APPLY; + break; + } + + if (tbl->next) + __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, + tbl->num_slots); + + tbl = tbl->next; + } + + CAM_DBG(CAM_REQ, + "Req[%lld] idx %d req_status %d link_hdl %x eof_trigger_type %x", + in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx, + in_q->slot[in_q->rd_idx].status, link->link_hdl, + eof_trigger_type); + + return eof_trigger_type; +} + /** * __cam_req_mgr_process_req() * @@ -1652,6 +1704,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, struct cam_req_mgr_connected_device *dev = NULL; struct cam_req_mgr_core_link *tmp_link = NULL; uint32_t max_retry = 0; + enum crm_req_eof_trigger_type eof_trigger_type; session = (struct cam_req_mgr_core_session *)link->parent; if (!session) { @@ -1669,10 +1722,11 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, * - if in no_req state, no new req */ CAM_DBG(CAM_REQ, - "SOF Req[%lld] idx %d req_status %d link_hdl %x wd_timeout %d ms", + "%s Req[%lld] idx %d req_status %d link_hdl %x wd_timeout %d ms trigger:%d", + ((trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"), in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx, in_q->slot[in_q->rd_idx].status, link->link_hdl, - in_q->slot[in_q->rd_idx].additional_timeout); + in_q->slot[in_q->rd_idx].additional_timeout, trigger); slot = &in_q->slot[in_q->rd_idx]; @@ -1680,10 +1734,11 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, (trigger != CAM_TRIGGER_POINT_EOF)) goto end; + eof_trigger_type = __cam_req_mgr_check_for_eof(link); + if ((trigger == CAM_TRIGGER_POINT_EOF) && - (!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) { - CAM_DBG(CAM_CRM, "Applying for last SOF fails"); - rc = -EINVAL; + (eof_trigger_type == CAM_REQ_EOF_TRIGGER_NONE)) { + CAM_DBG(CAM_CRM, "Not any request to schedule at EOF"); goto end; } @@ -1711,17 +1766,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, link->wq_congestion = true; else link->wq_congestion = false; + } - if (link->trigger_mask) { - CAM_ERR_RATE_LIMIT(CAM_CRM, - "Applying for last EOF fails"); - rc = -EINVAL; - goto end; - } - + if (slot->status != CRM_SLOT_STATUS_REQ_READY) { if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { rc = __cam_req_mgr_check_multi_sync_link_ready( - link, slot); + link, slot, trigger); } else { if (link->in_msync_mode) { CAM_DBG(CAM_CRM, @@ -1738,11 +1788,34 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } - rc = __cam_req_mgr_inject_delay(link->req.l_tbl, - slot->idx); - if (!rc) - rc = __cam_req_mgr_check_link_is_ready(link, - slot->idx, false); + /* + * Validate that if the req is ready to apply before + * checking the inject delay. + */ + rc = __cam_req_mgr_check_link_is_ready(link, + slot->idx, true); + + if (!rc) { + rc = __cam_req_mgr_inject_delay(link->req.l_tbl, + slot->idx, trigger); + if (rc < 0) + CAM_DBG(CAM_CRM, + "Req: %lld needs to inject delay at %s", + slot->req_id, + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"); + + if (!rc) + rc = __cam_req_mgr_check_link_is_ready(link, + slot->idx, false); + } + } + + if (!rc) { + if ((trigger == CAM_TRIGGER_POINT_SOF) && + (eof_trigger_type == CAM_REQ_EOF_TRIGGER_NOT_APPLY)) { + CAM_DBG(CAM_CRM, "EOF apply first"); + rc = -EAGAIN; + } } if (rc < 0) { @@ -1769,6 +1842,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, __cam_req_mgr_notify_frame_skip(link, trigger); __cam_req_mgr_validate_crm_wd_timer(link); goto end; + } else { + slot->status = CRM_SLOT_STATUS_REQ_READY; + CAM_DBG(CAM_REQ, + "linx_hdl %x Req[%lld] idx %d ready to apply", + link->link_hdl, in_q->slot[in_q->rd_idx].req_id, + in_q->rd_idx); } } @@ -1808,8 +1887,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->retry_cnt) link->retry_cnt = 0; - link->trigger_mask |= trigger; - /* Check for any long exposure settings */ __cam_req_mgr_validate_crm_wd_timer(link); @@ -1826,16 +1903,17 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, if (link->sync_link_sof_skip) link->sync_link_sof_skip = false; - if (link->trigger_mask == link->subscribe_event) { + /* + * Below two cases can move slot to APPLIED status, + * 1# there is no eof trigger request + * 2# eof trigger is applied and the devcies which need to + * be applied at SOF are also applied. + */ + if (((eof_trigger_type == CAM_REQ_EOF_TRIGGER_NONE) || + (eof_trigger_type == CAM_REQ_EOF_TRIGGER_APPLIED)) && + (trigger == CAM_TRIGGER_POINT_SOF)) { slot->status = CRM_SLOT_STATUS_REQ_APPLIED; - link->trigger_mask = 0; - if (!(atomic_read(&link->eof_event_cnt)) && - (trigger == CAM_TRIGGER_POINT_EOF)) { - link->subscribe_event &= ~CAM_TRIGGER_POINT_EOF; - CAM_DBG(CAM_CRM, - "Update link subscribe_event: %d", - link->subscribe_event); - } + CAM_DBG(CAM_CRM, "req %d is applied on link %x", slot->req_id, link->link_hdl); @@ -1937,7 +2015,6 @@ static struct cam_req_mgr_req_tbl *__cam_req_mgr_create_pd_tbl(int32_t delay) CAM_DBG(CAM_CRM, "pd= %d slots= %d", delay, tbl->num_slots); for (i = 0; i < MAX_REQ_SLOTS; i++) { tbl->slot[i].ops.apply_at_eof = false; - tbl->slot[i].ops.skip_next_frame = false; tbl->slot[i].ops.dev_hdl = -1; tbl->slot[i].ops.is_applied = false; } @@ -2217,7 +2294,6 @@ static int __cam_req_mgr_disconnect_link(struct cam_req_mgr_core_link *link) link_data.link_enable = 0; link_data.link_hdl = link->link_hdl; link_data.crm_cb = NULL; - link_data.subscribe_event = 0; /* Using device ops unlink devices */ for (i = 0; i < link->num_devs; i++) { @@ -2659,23 +2735,31 @@ int cam_req_mgr_process_add_req(void *priv, void *data) slot = &tbl->slot[idx]; slot->ops.is_applied = false; - if ((add_req->skip_before_applying & 0xFF) > slot->inject_delay) { - slot->inject_delay = (add_req->skip_before_applying & 0xFF); - if (add_req->skip_before_applying & SKIP_NEXT_FRAME) { - slot->ops.skip_next_frame = true; - slot->ops.dev_hdl = add_req->dev_hdl; - } - CAM_DBG(CAM_CRM, "Req_id %llu injecting delay %llu", + + if ((add_req->skip_at_sof & 0xFF) > slot->inject_delay_at_sof) { + slot->inject_delay_at_sof = (add_req->skip_at_sof & 0xFF); + CAM_DBG(CAM_CRM, + "Req_id %llu injecting delay %llu frame at SOF by %s", add_req->req_id, - (add_req->skip_before_applying & 0xFF)); + slot->inject_delay_at_sof, + device->dev_info.name); + } + + if ((add_req->skip_at_eof & 0xFF) > slot->inject_delay_at_eof) { + slot->inject_delay_at_eof = (add_req->skip_at_eof & 0xFF); + CAM_DBG(CAM_CRM, + "Req_id %llu injecting delay %llu frame at EOF by %s", + add_req->req_id, + slot->inject_delay_at_eof, + device->dev_info.name); } if (add_req->trigger_eof) { slot->ops.apply_at_eof = true; slot->ops.dev_hdl = add_req->dev_hdl; CAM_DBG(CAM_REQ, - "Req_id %llu added for EOF tigger for Device: %s", - add_req->req_id, device->dev_info.name); + "Req_id %llu slot:%d added for EOF tigger for Device: %s", + add_req->req_id, idx, device->dev_info.name); } if (slot->state != CRM_REQ_STATE_PENDING && @@ -2804,7 +2888,7 @@ int cam_req_mgr_process_error(void *priv, void *data) evt_data.dev_hdl = device->dev_hdl; evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_ERR; - evt_data.link_hdl = link->link_hdl; + evt_data.link_hdl = link->link_hdl; evt_data.req_id = err_info->req_id; evt_data.u.error = err_info->error; if (device->ops && @@ -2936,6 +3020,10 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) spin_unlock_bh(&link->link_state_spin_lock); + /* + * Move to next req at SOF only in case + * the rd_idx is updated at EOF. + */ if (in_q->slot[in_q->rd_idx].status == CRM_SLOT_STATUS_REQ_APPLIED) { /* * Do NOT reset req q slot data here, it can not be done @@ -3061,15 +3149,13 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req) dev_req->req_id = add_req->req_id; dev_req->link_hdl = add_req->link_hdl; dev_req->dev_hdl = add_req->dev_hdl; - dev_req->skip_before_applying = add_req->skip_before_applying; dev_req->trigger_eof = add_req->trigger_eof; + dev_req->skip_at_sof = add_req->skip_at_sof; + dev_req->skip_at_eof = add_req->skip_at_eof; if (dev_req->trigger_eof) { - link->subscribe_event |= CAM_TRIGGER_POINT_EOF; atomic_inc(&link->eof_event_cnt); - CAM_DBG(CAM_REQ, - "Req_id: %llu, eof_event_cnt: %d, link subscribe event: %d", - dev_req->req_id, link->eof_event_cnt, - link->subscribe_event); + CAM_DBG(CAM_REQ, "Req_id: %llu, eof_event_cnt: %d", + dev_req->req_id, link->eof_event_cnt); } task->process_cb = &cam_req_mgr_process_add_req; @@ -3147,35 +3233,38 @@ end: } static int __cam_req_mgr_check_for_dual_trigger( - struct cam_req_mgr_core_link *link) + struct cam_req_mgr_core_link *link, + uint32_t trigger) { int rc = -EAGAIN; - CAM_DBG(CAM_CRM, "trigger_cnt [%u: %u]", - link->trigger_cnt[0], link->trigger_cnt[1]); + CAM_DBG(CAM_CRM, "%s trigger_cnt [%u: %u]", + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF", + link->trigger_cnt[0][trigger], link->trigger_cnt[1][trigger]); - if (link->trigger_cnt[0] == link->trigger_cnt[1]) { - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; + if (link->trigger_cnt[0][trigger] == link->trigger_cnt[1][trigger]) { + link->trigger_cnt[0][trigger] = 0; + link->trigger_cnt[1][trigger] = 0; rc = 0; return rc; } - if ((link->trigger_cnt[0] && - (link->trigger_cnt[0] - link->trigger_cnt[1] > 1)) || - (link->trigger_cnt[1] && - (link->trigger_cnt[1] - link->trigger_cnt[0] > 1))) { + if ((link->trigger_cnt[0][trigger] && + (link->trigger_cnt[0][trigger] - link->trigger_cnt[1][trigger] > 1)) || + (link->trigger_cnt[1][trigger] && + (link->trigger_cnt[1][trigger] - link->trigger_cnt[0][trigger] > 1))) { CAM_WARN(CAM_CRM, "One of the devices could not generate trigger"); - link->trigger_cnt[0] = 0; - link->trigger_cnt[1] = 0; + link->trigger_cnt[0][trigger] = 0; + link->trigger_cnt[1][trigger] = 0; CAM_DBG(CAM_CRM, "Reset the trigger cnt"); return rc; } - CAM_DBG(CAM_CRM, "Only one device has generated trigger"); + CAM_DBG(CAM_CRM, "Only one device has generated trigger for %s", + (trigger == CAM_TRIGGER_POINT_SOF) ? "SOF" : "EOF"); return rc; } @@ -3308,13 +3397,14 @@ static int cam_req_mgr_cb_notify_trigger( struct cam_req_mgr_trigger_notify *trigger_data) { int32_t rc = 0, trigger_id = 0; + uint32_t trigger; struct crm_workq_task *task = NULL; struct cam_req_mgr_core_link *link = NULL; struct cam_req_mgr_trigger_notify *notify_trigger; struct crm_task_payload *task_data; if (!trigger_data) { - CAM_ERR(CAM_CRM, "sof_data is NULL"); + CAM_ERR(CAM_CRM, "trigger_data is NULL"); rc = -EINVAL; goto end; } @@ -3327,10 +3417,20 @@ static int cam_req_mgr_cb_notify_trigger( goto end; } - trigger_id = trigger_data->trigger_id; + CAM_DBG(CAM_REQ, "link_hdl %x frame_id %lld, trigger %x\n", + trigger_data->link_hdl, + trigger_data->frame_id, + trigger_data->trigger); + trigger_id = trigger_data->trigger_id; + trigger = trigger_data->trigger; + + /* + * Reduce the workq overhead when there is + * not any eof event found. + */ if ((!atomic_read(&link->eof_event_cnt)) && - (trigger_data->trigger == CAM_TRIGGER_POINT_EOF)) { + (trigger == CAM_TRIGGER_POINT_EOF)) { CAM_DBG(CAM_CRM, "Not any request to schedule at EOF"); goto end; } @@ -3344,14 +3444,14 @@ static int cam_req_mgr_cb_notify_trigger( } if ((link->watchdog) && (link->watchdog->pause_timer) && - (trigger_data->trigger == CAM_TRIGGER_POINT_SOF)) + (trigger == CAM_TRIGGER_POINT_SOF)) link->watchdog->pause_timer = false; if (link->dual_trigger) { if ((trigger_id >= 0) && (trigger_id < CAM_REQ_MGR_MAX_TRIGGERS)) { - link->trigger_cnt[trigger_id]++; - rc = __cam_req_mgr_check_for_dual_trigger(link); + link->trigger_cnt[trigger_id][trigger]++; + rc = __cam_req_mgr_check_for_dual_trigger(link, trigger); if (rc) { spin_unlock_bh(&link->link_state_spin_lock); goto end; @@ -3424,7 +3524,6 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, struct cam_req_mgr_connected_device *dev; struct cam_req_mgr_req_tbl *pd_tbl; enum cam_pipeline_delay max_delay; - uint32_t subscribe_event = 0; uint32_t num_trigger_devices = 0; if (link_info->version == VERSION_1) { if (link_info->u.link_info_v1.num_devices > @@ -3512,8 +3611,6 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, } if (dev->dev_info.p_delay > max_delay) max_delay = dev->dev_info.p_delay; - - subscribe_event |= (uint32_t)dev->dev_info.trigger; } if (dev->dev_info.trigger_on) @@ -3528,12 +3625,10 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link, goto error; } - link->subscribe_event = subscribe_event; link_data.link_enable = 1; link_data.link_hdl = link->link_hdl; link_data.crm_cb = &cam_req_mgr_ops; link_data.max_delay = max_delay; - link_data.subscribe_event = subscribe_event; if (num_trigger_devices == CAM_REQ_MGR_MAX_TRIGGERS) link->dual_trigger = true; @@ -3968,6 +4063,11 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info) goto setup_failed; } + link->trigger_cnt[0][0] = 0; + link->trigger_cnt[0][1] = 0; + link->trigger_cnt[1][0] = 0; + link->trigger_cnt[1][1] = 0; + mutex_unlock(&link->lock); mutex_unlock(&g_crm_core_dev->crm_lock); return rc; diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index ffba72cf3c..f98a2a74bc 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_CORE_H_ #define _CAM_REQ_MGR_CORE_H_ @@ -42,6 +42,16 @@ #define VERSION_2 2 #define CAM_REQ_MGR_MAX_TRIGGERS 2 +/** + * enum crm_req_eof_trigger_type + * @codes: to identify which type of eof trigger for next slot + */ +enum crm_req_eof_trigger_type { + CAM_REQ_EOF_TRIGGER_NONE, + CAM_REQ_EOF_TRIGGER_NOT_APPLY, + CAM_REQ_EOF_TRIGGER_APPLIED, +}; + /** * enum crm_workq_task_type * @codes: to identify which type of task is present @@ -105,6 +115,7 @@ enum crm_req_state { * NO_REQ : empty slot * REQ_ADDED : new entry in slot * REQ_PENDING : waiting for next trigger to apply + * REQ_READY : req has ready * REQ_APPLIED : req is sent to all devices * INVALID : invalid state */ @@ -112,6 +123,7 @@ enum crm_slot_status { CRM_SLOT_STATUS_NO_REQ, CRM_SLOT_STATUS_REQ_ADDED, CRM_SLOT_STATUS_REQ_PENDING, + CRM_SLOT_STATUS_REQ_READY, CRM_SLOT_STATUS_REQ_APPLIED, CRM_SLOT_STATUS_INVALID, }; @@ -186,34 +198,34 @@ struct cam_req_mgr_apply { * struct crm_tbl_slot_special_ops * @dev_hdl : Device handle who requested for special ops * @apply_at_eof : Boolean Identifier for request to be applied at EOF - * @skip_next_frame : Flag to drop the frame after skip_before_apply frame * @is_applied : Flag to identify if request is already applied to device * in previous frame */ struct crm_tbl_slot_special_ops { int32_t dev_hdl; bool apply_at_eof; - bool skip_next_frame; bool is_applied; }; /** * struct cam_req_mgr_tbl_slot - * @idx : slot index - * @req_ready_map : mask tracking which all devices have request ready - * @state : state machine for life cycle of a slot - * @inject_delay : insert extra bubbling for flash type of use cases - * @ops : special operation for the table slot - * e.g. - * skip_next frame: in case of applying one device - * and skip others - * apply_at_eof: device that needs to apply at EOF + * @idx : slot index + * @req_ready_map : mask tracking which all devices have request ready + * @state : state machine for life cycle of a slot + * @inject_delay_at_sof : insert extra bubbling for flash type of use cases + * @inject_delay_at_eof : insert extra bubbling for flash type of use cases + * @ops : special operation for the table slot + * e.g. + * skip_next frame: in case of applying one device + * and skip others + * apply_at_eof: device that needs to apply at EOF */ struct cam_req_mgr_tbl_slot { int32_t idx; uint32_t req_ready_map; enum crm_req_state state; - uint32_t inject_delay; + uint32_t inject_delay_at_sof; + uint32_t inject_delay_at_eof; struct crm_tbl_slot_special_ops ops; }; @@ -342,9 +354,6 @@ struct cam_req_mgr_connected_device { * @parent : pvt data - link's parent is session * @lock : mutex lock to guard link data operations * @link_state_spin_lock : spin lock to protect link state variable - * @subscribe_event : irqs that link subscribes, IFE should send - * notification to CRM at those hw events. - * @trigger_mask : mask on which irq the req is already applied * @sync_link : array of pointer to the sync link for synchronization * @num_sync_links : num of links sync associated with this link * @sync_link_sof_skip : flag determines if a pkt is not available for a given @@ -390,8 +399,6 @@ struct cam_req_mgr_core_link { void *parent; struct mutex lock; spinlock_t link_state_spin_lock; - uint32_t subscribe_event; - uint32_t trigger_mask; struct cam_req_mgr_core_link *sync_link[MAXIMUM_LINKS_PER_SESSION - 1]; int32_t num_sync_links; @@ -408,7 +415,7 @@ struct cam_req_mgr_core_link { uint64_t sof_timestamp; uint64_t prev_sof_timestamp; bool dual_trigger; - uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS]; + uint32_t trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS][CAM_TRIGGER_MAX_POINTS]; atomic_t eof_event_cnt; bool skip_init_frame; uint64_t last_sof_trigger_jiffies; diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index 231cf397f3..b6807ed4a7 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/cam_req_mgr/cam_req_mgr_interface.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_REQ_MGR_INTERFACE_H @@ -23,8 +23,6 @@ struct cam_req_mgr_flush_request; struct cam_req_mgr_link_evt_data; struct cam_req_mgr_dump_info; -#define SKIP_NEXT_FRAME 0x100 - /* Request Manager -- camera device driver interface */ /** * @brief: camera kernel drivers to cam req mgr communication @@ -119,9 +117,11 @@ enum cam_pipeline_delay { /** * @CAM_TRIGGER_POINT_SOF : Trigger point for Start Of Frame * @CAM_TRIGGER_POINT_EOF : Trigger point for End Of Frame + * @CAM_TRIGGER_MAX_POINTS : Maximum number of trigger point */ #define CAM_TRIGGER_POINT_SOF (1 << 0) #define CAM_TRIGGER_POINT_EOF (1 << 1) +#define CAM_TRIGGER_MAX_POINTS 2 /** * enum cam_req_status @@ -266,7 +266,9 @@ struct cam_req_mgr_error_notify { * @link_hdl : link identifier * @dev_hdl : device handle which has sent this req id * @req_id : req id which device is ready to process - * @skip_before_applying : before applying req mgr introduce bubble + * @skip_at_sof : before applying req mgr introduce bubble + * by not sending request to devices. ex: IFE and Flash + * @skip_at_eof : before applying req mgr introduce bubble * by not sending request to devices. ex: IFE and Flash * @trigger_eof : to identify that one of the device at this slot needs * to be apply at EOF @@ -275,7 +277,8 @@ struct cam_req_mgr_add_request { int32_t link_hdl; int32_t dev_hdl; uint64_t req_id; - uint32_t skip_before_applying; + uint32_t skip_at_sof; + uint32_t skip_at_eof; bool trigger_eof; }; @@ -316,7 +319,6 @@ struct cam_req_mgr_device_info { * @dev_hdl : device handle for reference * @max_delay : max pipeline delay on this link * @crm_cb : callback funcs to communicate with req mgr - * @subscribe_event : the mask of trigger points this link subscribes * @trigger_id : Unique ID provided to the triggering device */ struct cam_req_mgr_core_dev_link_setup { @@ -325,7 +327,6 @@ struct cam_req_mgr_core_dev_link_setup { int32_t dev_hdl; enum cam_pipeline_delay max_delay; struct cam_req_mgr_crm_cb *crm_cb; - uint32_t subscribe_event; int32_t trigger_id; }; diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index aa761a729c..9c0d7abd04 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -374,11 +374,10 @@ static int cam_actuator_update_req_mgr( int rc = 0; struct cam_req_mgr_add_request add_req; + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = a_ctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl; - add_req.skip_before_applying = 0; - add_req.trigger_eof = false; if (a_ctrl->bridge_intf.crm_cb && a_ctrl->bridge_intf.crm_cb->add_req) { diff --git a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 914c66cc8b..db065345d4 100644 --- a/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1263,26 +1263,30 @@ update_req_mgr: CAM_PKT_NOP_OPCODE) || ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS)) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = fctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; add_req.dev_hdl = fctrl->bridge_intf.device_hdl; if ((csl_packet->header.op_code & 0xFFFFF) == - CAM_FLASH_PACKET_OPCODE_SET_OPS) - add_req.skip_before_applying = 1; - else - add_req.skip_before_applying = 0; + CAM_FLASH_PACKET_OPCODE_SET_OPS) { + add_req.trigger_eof = true; + add_req.skip_at_sof = 1; + } if (fctrl->bridge_intf.crm_cb && - fctrl->bridge_intf.crm_cb->add_req) + fctrl->bridge_intf.crm_cb->add_req) { rc = fctrl->bridge_intf.crm_cb->add_req(&add_req); - if (rc) { - CAM_ERR(CAM_FLASH, - "Failed in adding request: %llu to request manager", - csl_packet->header.request_id); - return rc; + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in adding request: %llu to request manager", + csl_packet->header.request_id); + return rc; + } + CAM_DBG(CAM_FLASH, + "add req %lld to req_mgr, trigger_eof %d", + add_req.req_id, add_req.trigger_eof); } - CAM_DBG(CAM_FLASH, "add req to req_mgr= %lld", add_req.req_id); } return rc; } @@ -1507,7 +1511,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) switch (cmn_hdr->cmd_type) { case CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE: { CAM_DBG(CAM_FLASH, - "CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE cmd called"); + "CAMERA_SENSOR_FLASH_CMD_TYPE_FIRE cmd called, req:%lld", + csl_packet->header.request_id); if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { @@ -1545,7 +1550,8 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) = flash_operation_info->led_current_ma[i]; CAM_DBG(CAM_FLASH, - "FLASH_CMD_TYPE op:%d", flash_data->opcode); + "FLASH_CMD_TYPE op:%d, req:%lld", + flash_data->opcode, csl_packet->header.request_id); if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_FIREDURATION) { @@ -1739,29 +1745,34 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) CAM_PKT_NOP_OPCODE) || ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS)) { + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = fctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; add_req.dev_hdl = fctrl->bridge_intf.device_hdl; if ((csl_packet->header.op_code & 0xFFFFF) == CAM_FLASH_PACKET_OPCODE_SET_OPS) { - add_req.skip_before_applying |= SKIP_NEXT_FRAME; add_req.trigger_eof = true; - - if (flash_data && (flash_data->opcode != - CAMERA_SENSOR_FLASH_OP_FIREDURATION)) - add_req.skip_before_applying |= 1; - else - add_req.skip_before_applying = 0; - } else { - add_req.skip_before_applying = 0; + if (flash_data->opcode == CAMERA_SENSOR_FLASH_OP_OFF) { + add_req.skip_at_sof = 1; + add_req.skip_at_eof = 1; + } else + add_req.skip_at_sof = 1; } - CAM_DBG(CAM_FLASH, - "add req to req_mgr= %lld:: trigger_eof: %d", - add_req.req_id, add_req.trigger_eof); + if (fctrl->bridge_intf.crm_cb && - fctrl->bridge_intf.crm_cb->add_req) - fctrl->bridge_intf.crm_cb->add_req(&add_req); + fctrl->bridge_intf.crm_cb->add_req) { + rc = fctrl->bridge_intf.crm_cb->add_req(&add_req); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in adding request: %llu to request manager", + csl_packet->header.request_id); + return rc; + } + CAM_DBG(CAM_FLASH, + "add req %lld to req_mgr, trigger_eof %d", + add_req.req_id, add_req.trigger_eof); + } } return rc; diff --git a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 8ca672a01a..85e0fbeacc 100644 --- a/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -20,13 +20,12 @@ static int cam_sensor_update_req_mgr( int rc = 0; struct cam_req_mgr_add_request add_req; + memset(&add_req, 0, sizeof(add_req)); add_req.link_hdl = s_ctrl->bridge_intf.link_hdl; add_req.req_id = csl_packet->header.request_id; CAM_DBG(CAM_SENSOR, " Rxed Req Id: %llu", csl_packet->header.request_id); add_req.dev_hdl = s_ctrl->bridge_intf.device_hdl; - add_req.skip_before_applying = 0; - add_req.trigger_eof = false; if (s_ctrl->bridge_intf.crm_cb && s_ctrl->bridge_intf.crm_cb->add_req) { rc = s_ctrl->bridge_intf.crm_cb->add_req(&add_req);