Loading drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +304 −209 Original line number Original line Diff line number Diff line Loading @@ -43,9 +43,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->subscribe_event = 0; link->subscribe_event = 0; link->trigger_mask = 0; link->trigger_mask = 0; link->sync_link = 0; link->sync_link = 0; link->sof_counter = 0; link->sync_self_ref = 0; link->frame_skip_flag = false; link->sync_link_sof_skip = false; link->sync_link_sof_skip = false; link->open_req_cnt = 0; link->open_req_cnt = 0; link->last_flush_id = 0; link->last_flush_id = 0; Loading Loading @@ -143,31 +140,35 @@ static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val) } } /** /** * __cam_req_mgr_validate_inject_delay() * __cam_req_mgr_inject_delay() * * * @brief : Check if any pd device is introducing inject delay * @brief : Check if any pd device is injecting delay * @tbl : cam_req_mgr_req_tbl * @tbl : cam_req_mgr_req_tbl * @curr_idx : slot idx * @curr_idx : slot idx * * * @return : 0 for success, negative for failure * @return : 0 for success, negative for failure */ */ static int __cam_req_mgr_validate_inject_delay( static int __cam_req_mgr_inject_delay( struct cam_req_mgr_req_tbl *tbl, struct cam_req_mgr_req_tbl *tbl, int32_t curr_idx) int32_t curr_idx) { { struct cam_req_mgr_tbl_slot *slot = NULL; struct cam_req_mgr_tbl_slot *slot = NULL; int rc = 0; while (tbl) { while (tbl) { slot = &tbl->slot[curr_idx]; slot = &tbl->slot[curr_idx]; if (slot->inject_delay > 0) { if (slot->inject_delay > 0) { slot->inject_delay--; slot->inject_delay--; return -EAGAIN; CAM_DBG(CAM_CRM, "Delay injected by pd %d device", tbl->pd); rc = -EAGAIN; } } __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, tbl->num_slots); tbl->num_slots); tbl = tbl->next; tbl = tbl->next; } } return 0; return rc; } } /** /** Loading Loading @@ -209,19 +210,6 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, traverse_data->in_q->slot[curr_idx].skip_idx); traverse_data->in_q->slot[curr_idx].skip_idx); if ((traverse_data->self_link == true) && (!traverse_data->inject_delay_chk)) { rc = __cam_req_mgr_validate_inject_delay(tbl, curr_idx); if (rc) { CAM_DBG(CAM_CRM, "Injecting Delay of one frame"); apply_data[tbl->pd].req_id = -1; /* This pd tbl not ready to proceed with asked idx */ SET_FAILURE_BIT(traverse_data->result, tbl->pd); return -EAGAIN; } traverse_data->inject_delay_chk = true; } /* Check if req is ready or in skip mode or pd tbl is in skip mode */ /* Check if req is ready or in skip mode or pd tbl is in skip mode */ if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY || if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY || traverse_data->in_q->slot[curr_idx].skip_idx == 1 || traverse_data->in_q->slot[curr_idx].skip_idx == 1 || Loading Loading @@ -552,14 +540,12 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, * traversed through * traversed through * @idx : index within input request queue * @idx : index within input request queue * @validate_only : Whether to validate only and/or update settings * @validate_only : Whether to validate only and/or update settings * @self_link : To indicate whether the validation is for the given link or * other sync link * * * @return : 0 for success, negative for failure * @return : 0 for success, negative for failure * * */ */ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, int32_t idx, bool validate_only, bool self_link) int32_t idx, bool validate_only) { { int rc; int rc; struct cam_req_mgr_traverse traverse_data; struct cam_req_mgr_traverse traverse_data; Loading @@ -581,19 +567,16 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.in_q = in_q; traverse_data.in_q = in_q; traverse_data.result = 0; traverse_data.result = 0; traverse_data.validate_only = validate_only; traverse_data.validate_only = validate_only; traverse_data.self_link = self_link; traverse_data.inject_delay_chk = false; traverse_data.open_req_cnt = link->open_req_cnt; traverse_data.open_req_cnt = link->open_req_cnt; /* /* * Traverse through all pd tables, if result is success, * Traverse through all pd tables, if result is success, * apply the settings * apply the settings */ */ rc = __cam_req_mgr_traverse(&traverse_data); rc = __cam_req_mgr_traverse(&traverse_data); CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "SOF: idx %d self_link %d validate %d result %x pd_mask %x rc %d", "SOF: idx %d result %x pd_mask %x rc %d", idx, traverse_data.self_link, traverse_data.validate_only, idx, traverse_data.result, link->pd_mask, rc); traverse_data.result, link->pd_mask, rc); if (!rc && traverse_data.result == link->pd_mask) { if (!rc && traverse_data.result == link->pd_mask) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, Loading Loading @@ -642,113 +625,198 @@ static int32_t __cam_req_mgr_find_slot_for_req( } } /** /** * __cam_req_mgr_reset_sof_cnt() * __cam_req_mgr_check_sync_for_mslave() * * * @brief : the sof_count for both the links are reset * @brief : Processes requests during sync mode [master-slave] * @link : pointer to link whose input queue and req tbl are * Here master corresponds to the link having a higher * max_delay (pd) compared to the slave link. * @link : Pointer to link whose input queue and req tbl are * traversed through * traversed through * @slot : Pointer to the current slot being processed * @return : 0 for success, negative for failure * * */ */ static void __cam_req_mgr_reset_sof_cnt( static int __cam_req_mgr_check_sync_for_mslave( struct cam_req_mgr_core_link *link) struct cam_req_mgr_core_link *link, struct cam_req_mgr_slot *slot) { { link->sof_counter = -1; struct cam_req_mgr_core_link *sync_link = NULL; link->sync_link->sof_counter = -1; int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, rc = 0; link->frame_skip_flag = false; int64_t req_id = 0, sync_req_id = 0; if (!link->sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } sync_link = link->sync_link; req_id = slot->req_id; CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d", "link_hdl %x req %lld frame_skip_flag %d ", link->link_hdl, link->sof_counter, link->link_hdl, req_id, link->sync_link_sof_skip); link->sync_link->sof_counter, link->frame_skip_flag); if (sync_link->sync_link_sof_skip) { CAM_DBG(CAM_CRM, "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; } } /** if (link->is_master) { * __cam_req_mgr_sof_cnt_initialize() rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); * if (rc) { * @brief : when the sof count is intially -1 it increments count CAM_DBG(CAM_CRM, * and computes the sync_self_ref for this link "Skip Process Req: %lld on link: %x", * the count needs to be wrapped back starting from 0 req_id, link->link_hdl); * @link : pointer to link whose input queue and req tbl are link->sync_link_sof_skip = true; * traversed through return rc; * } */ static void __cam_req_mgr_sof_cnt_initialize( struct cam_req_mgr_core_link *link) { link->sof_counter++; link->sync_self_ref = link->sof_counter - link->sync_link->sof_counter; if (sync_link->initial_skip) { CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", sync_link->link_hdl); return -EAGAIN; } rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); if (rc) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link_hdl %x self_counter %lld other_counter %lld", "Req: %lld [master] not ready on link: %x, rc=%d", link->link_hdl, link->sof_counter, req_id, link->link_hdl, rc); link->sync_link->sof_counter); return rc; } } /** prev_idx = slot->idx; * __cam_req_mgr_wrap_sof_cnt() __cam_req_mgr_dec_idx(&prev_idx, * (link->max_delay - sync_link->max_delay), * @brief : once the sof count reaches a predefined maximum link->req.in_q->num_slots); * the count needs to be wrapped back starting from 0 * @link : pointer to link whose input queue and req tbl are rd_idx = sync_link->req.in_q->rd_idx; * traversed through sync_req_id = link->req.in_q->slot[prev_idx].req_id; * if (sync_req_id != -1) { */ sync_slot_idx = __cam_req_mgr_find_slot_for_req( static void __cam_req_mgr_wrap_sof_cnt( sync_link->req.in_q, sync_req_id); struct cam_req_mgr_core_link *link) { link->sof_counter = (MAX_SYNC_COUNT - (link->sync_link->sof_counter)); link->sync_link->sof_counter = 0; if (sync_slot_idx == -1) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld", "Prev Req: %lld [master] not found on link: %x [slave]", link->link_hdl, link->sof_counter, sync_req_id, sync_link->link_hdl); link->sync_link->link_hdl, link->sync_link->sof_counter); return -EINVAL; } } /** if ((sync_link->req.in_q->slot[sync_slot_idx].status != * __cam_req_mgr_validate_sof_cnt() CRM_SLOT_STATUS_REQ_APPLIED) && * ((sync_slot_idx - rd_idx) >= 1) && * @brief : validates sof count difference for a given link (sync_link->req.in_q->slot[rd_idx].status != * @link : pointer to link whose input queue and req tbl are CRM_SLOT_STATUS_REQ_APPLIED)) { * traversed through CAM_DBG(CAM_CRM, * @sync_link : pointer to the sync link "Prev Req: %lld [master] not next on link: %x [slave]", * @return : 0 for success, negative for failure sync_req_id, * sync_link->link_hdl); */ return -EINVAL; static int __cam_req_mgr_validate_sof_cnt( } struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_link *sync_link) { int64_t sync_diff = 0; int rc = 0; if (link->sof_counter == MAX_SYNC_COUNT) rc = __cam_req_mgr_check_link_is_ready(sync_link, __cam_req_mgr_wrap_sof_cnt(link); sync_slot_idx, true); if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Req: %lld not ready on [slave] link: %x, rc=%d", sync_req_id, sync_link->link_hdl, rc); return rc; } } } else { if (link->initial_skip) link->initial_skip = false; sync_diff = link->sof_counter - sync_link->sof_counter; sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, req_id); if (sync_slot_idx == -1) { CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [master]", req_id, sync_link->link_hdl); return -EINVAL; } if (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld", "Req: %lld [master] not applied yet: %x", link->link_hdl, link->sof_counter, req_id, sync_link->link_hdl); sync_link->sof_counter, sync_diff, link->sync_self_ref); return -EAGAIN; } if (sync_diff > SYNC_LINK_SOF_CNT_MAX_LMT) { rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); link->sync_link->frame_skip_flag = true; if (rc) { CAM_WARN(CAM_CRM, CAM_DBG(CAM_CRM, "Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld", "Skip Process Req: %lld on link: %x", link->link_hdl, link->sof_counter, req_id, link->link_hdl); sync_link->sof_counter, link->sync_self_ref); link->sync_link_sof_skip = true; rc = -EPERM; return rc; } } next_idx = link->req.in_q->rd_idx; rd_idx = sync_link->req.in_q->rd_idx; __cam_req_mgr_inc_idx(&next_idx, (sync_link->max_delay - link->max_delay), link->req.in_q->num_slots); sync_req_id = link->req.in_q->slot[next_idx].req_id; sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, sync_req_id); if (sync_slot_idx == -1) { CAM_DBG(CAM_CRM, "Next Req: %lld [slave] not found on link: %x [master]", sync_req_id, sync_link->link_hdl); return -EINVAL; } if ((sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) && ((sync_slot_idx - rd_idx) >= 1) && (sync_link->req.in_q->slot[rd_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Next Req: %lld [slave] not next on link: %x [master]", sync_req_id, sync_link->link_hdl); return -EINVAL; } rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true); if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Next Req: %lld [slave] not ready on [master] link: %x, rc=%d", sync_req_id, sync_link->link_hdl, rc); return rc; return rc; } } } CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); /* * At this point all validation is successfully done * and we can proceed to apply the given request. * Ideally the next call should return success. */ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false); if (rc) CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc); return 0; } /** /** * __cam_req_mgr_process_sync_req() * __cam_req_mgr_check_sync_request_is_ready() * * * @brief : processes requests during sync mode * @brief : processes requests during sync mode * @link : pointer to link whose input queue and req tbl are * @link : pointer to link whose input queue and req tbl are Loading @@ -757,13 +825,13 @@ static int __cam_req_mgr_validate_sof_cnt( * @return : 0 for success, negative for failure * @return : 0 for success, negative for failure * * */ */ static int __cam_req_mgr_process_sync_req( static int __cam_req_mgr_check_sync_req_is_ready( struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_link *link, struct cam_req_mgr_slot *slot) struct cam_req_mgr_slot *slot) { { struct cam_req_mgr_core_link *sync_link = NULL; struct cam_req_mgr_core_link *sync_link = NULL; int64_t req_id = 0; int64_t req_id = 0; int sync_slot_idx = 0, rc = 0; int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; if (!link->sync_link) { if (!link->sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); CAM_ERR(CAM_CRM, "Sync link null"); Loading @@ -774,94 +842,82 @@ static int __cam_req_mgr_process_sync_req( req_id = slot->req_id; req_id = slot->req_id; CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, "link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld", "link_hdl %x req %lld frame_skip_flag %d ", link->link_hdl, req_id, link->sync_self_ref, link->sof_counter, link->link_hdl, req_id, link->sync_link_sof_skip); link->frame_skip_flag, link->sync_link->sync_self_ref); if (sync_link->sync_link_sof_skip) { if (sync_link->sync_link_sof_skip) { CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, "No req applied on corresponding SOF on sync link: %x", "No req applied on corresponding SOF on sync link: %x", sync_link->link_hdl); sync_link->link_hdl); sync_link->sync_link_sof_skip = false; sync_link->sync_link_sof_skip = false; /*It is to manage compensate inject delay for each pd*/ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true); return -EAGAIN; return -EINVAL; } } if (link->sof_counter == -1) { rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); __cam_req_mgr_sof_cnt_initialize(link); if (rc) { } else if ((link->frame_skip_flag) && CAM_DBG(CAM_CRM, (sync_link->sync_self_ref != -1)) { "Skip Process Req: %lld on link: %x", CAM_DBG(CAM_REQ, "Link[%x] Req[%lld] Resetting values ", req_id, link->link_hdl); link->link_hdl, req_id); link->sync_link_sof_skip = true; __cam_req_mgr_reset_sof_cnt(link); return rc; __cam_req_mgr_sof_cnt_initialize(link); } else { link->sof_counter++; } } rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true); rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); if (rc) { if (rc) { CAM_DBG(CAM_REQ, CAM_DBG(CAM_CRM, "Req: %lld [My link] not ready on link: %x, rc=%d", "Req: %lld [My link] not ready on link: %x, rc=%d", req_id, link->link_hdl, rc); req_id, link->link_hdl, rc); link->sync_link_sof_skip = true; link->sync_link_sof_skip = true; goto failure; return rc; } } sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, req_id); sync_link->req.in_q, req_id); if (sync_slot_idx == -1) { if (sync_slot_idx != -1) { CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]", rc = __cam_req_mgr_check_link_is_ready( req_id, sync_link->link_hdl); sync_link, sync_slot_idx, true, false); link->sync_link_sof_skip = true; CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d", return -EINVAL; sync_slot_idx, sync_link->req.in_q->slot[sync_slot_idx].status, rc); } else { CAM_DBG(CAM_CRM, "sync_slot_idx=%d, rc=%d", sync_slot_idx, rc); } } if ((sync_slot_idx != -1) && sync_rd_idx = sync_link->req.in_q->rd_idx; ((sync_link->req.in_q->slot[sync_slot_idx].status == if ((sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) { CRM_SLOT_STATUS_REQ_APPLIED) && rc = __cam_req_mgr_validate_sof_cnt(link, sync_link); ((sync_slot_idx - sync_rd_idx) >= 1) && if (rc) { (sync_link->req.in_q->slot[sync_rd_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "Req: %lld validate failed: %x", "Req: %lld [other link] not next req to be applied on link: %x", req_id, sync_link->link_hdl); req_id, sync_link->link_hdl); goto failure; link->sync_link_sof_skip = true; return -EAGAIN; } rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true); if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Req: %lld not ready on [other link] link: %x, rc=%d", req_id, sync_link->link_hdl, rc); link->sync_link_sof_skip = true; return rc; } } CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); req_id, link->link_hdl); /* /* * At this point all validation is successfully done * At this point all validation is successfully done * and we can proceed to apply the given request. * and we can proceed to apply the given request. * Ideally the next call should return success. * Ideally the next call should return success. */ */ rc = __cam_req_mgr_check_link_is_ready(link, rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false); slot->idx, false, true); if (rc) if (rc) CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc); CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc); } else { CAM_DBG(CAM_REQ, "Req: %lld [Other link] not ready to apply on link: %x", req_id, sync_link->link_hdl); rc = -EPERM; link->sync_link_sof_skip = true; goto failure; } return rc; failure: return 0; link->sof_counter--; return rc; } } /** /** Loading Loading @@ -922,11 +978,21 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, goto error; goto error; } } if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) && rc = __cam_req_mgr_process_sync_req(link, slot); (link->sync_link)) { if (link->is_master || link->sync_link->is_master) rc = __cam_req_mgr_check_sync_for_mslave( link, slot); else else rc = __cam_req_mgr_check_sync_req_is_ready( link, slot); } else { rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); if (!rc) rc = __cam_req_mgr_check_link_is_ready(link, rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false, true); slot->idx, false); } if (rc < 0) { if (rc < 0) { /* /* Loading Loading @@ -970,9 +1036,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } spin_unlock_bh(&link->link_state_spin_lock); spin_unlock_bh(&link->link_state_spin_lock); if (link->sync_link_sof_skip) link->sync_link_sof_skip = false; if (link->trigger_mask == link->subscribe_event) { if (link->trigger_mask == link->subscribe_event) { slot->status = CRM_SLOT_STATUS_REQ_APPLIED; slot->status = CRM_SLOT_STATUS_REQ_APPLIED; link->trigger_mask = 0; link->trigger_mask = 0; Loading Loading @@ -1481,21 +1544,14 @@ static void __cam_req_mgr_unreserve_link( for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i] == link) if (session->links[i] == link) session->links[i] = NULL; session->links[i] = NULL; } if ((session->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC) && if (link->sync_link) { (link->sync_link)) { if (link->sync_link == session->links[i]) /* * make sure to unlink sync setup under the assumption * of only having 2 links in a given session */ session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i]) session->links[i]->sync_link = NULL; session->links[i]->sync_link = NULL; } } } } link->sync_link = NULL; session->num_links--; session->num_links--; CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); mutex_unlock(&session->lock); mutex_unlock(&session->lock); Loading Loading @@ -1769,8 +1825,9 @@ int cam_req_mgr_process_add_req(void *priv, void *data) trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); if (slot->req_ready_map == tbl->dev_mask) { if (slot->req_ready_map == tbl->dev_mask) { CAM_DBG(CAM_REQ, "idx %d req_id %lld pd %d SLOT READY", CAM_DBG(CAM_REQ, idx, add_req->req_id, tbl->pd); "link 0x%x idx %d req_id %lld pd %d SLOT READY", link->link_hdl, idx, add_req->req_id, tbl->pd); slot->state = CRM_REQ_STATE_READY; slot->state = CRM_REQ_STATE_READY; } } mutex_unlock(&link->req.lock); mutex_unlock(&link->req.lock); Loading Loading @@ -2673,6 +2730,33 @@ int cam_req_mgr_schedule_request( return rc; return rc; } } /** * __cam_req_mgr_set_master_link() * * @brief : Each links sets its max pd delay based on the devices on the * link. The link with higher pd is assigned master. * @link1 : One of the sync links * @link2 : The other sync link */ static void __cam_req_mgr_set_master_link( struct cam_req_mgr_core_link *link1, struct cam_req_mgr_core_link *link2) { if (link1->max_delay > link2->max_delay) { link1->is_master = true; link2->initial_skip = true; } else if (link2->max_delay > link1->max_delay) { link2->is_master = true; link1->initial_skip = true; } CAM_DBG(CAM_CRM, "link_hdl1[0x%x] is_master [%u] link_hdl2[0x%x] is_master[%u]", link1->link_hdl, link1->is_master, link2->link_hdl, link2->is_master); } int cam_req_mgr_sync_config( int cam_req_mgr_sync_config( struct cam_req_mgr_sync_mode *sync_info) struct cam_req_mgr_sync_mode *sync_info) { { Loading @@ -2693,6 +2777,12 @@ int cam_req_mgr_sync_config( return -EINVAL; return -EINVAL; } } if ((sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC) && (sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC)) { CAM_ERR(CAM_CRM, "Invalid sync mode %d", sync_info->sync_mode); return -EINVAL; } if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) { if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) { CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x", CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x", sync_info->link_hdls[0], sync_info->link_hdls[1]); sync_info->link_hdls[0], sync_info->link_hdls[1]); Loading Loading @@ -2729,17 +2819,22 @@ int cam_req_mgr_sync_config( goto done; goto done; } } link1->sof_counter = -1; link1->sync_self_ref = -1; link1->frame_skip_flag = false; link1->sync_link_sof_skip = false; link1->sync_link_sof_skip = false; link1->sync_link = link2; link1->sync_link = NULL; link2->sof_counter = -1; link2->sync_self_ref = -1; link2->frame_skip_flag = false; link2->sync_link_sof_skip = false; link2->sync_link_sof_skip = false; link2->sync_link = NULL; link1->is_master = false; link2->is_master = false; link1->initial_skip = false; link2->initial_skip = false; if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { link1->sync_link = link2; link2->sync_link = link1; link2->sync_link = link1; __cam_req_mgr_set_master_link(link1, link2); } cam_session->sync_mode = sync_info->sync_mode; cam_session->sync_mode = sync_info->sync_mode; CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, Loading drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h +6 −12 Original line number Original line Diff line number Diff line Loading @@ -135,9 +135,6 @@ enum cam_req_mgr_link_state { * @apply_data : pointer which various tables will update during traverse * @apply_data : pointer which various tables will update during traverse * @in_q : input request queue pointer * @in_q : input request queue pointer * @validate_only : Whether to validate only and/or update settings * @validate_only : Whether to validate only and/or update settings * @self_link : To indicate whether the check is for the given link or * the other sync link * @inject_delay_chk : if inject delay has been validated for all pd devices * @open_req_cnt : Count of open requests yet to be serviced in the kernel. * @open_req_cnt : Count of open requests yet to be serviced in the kernel. */ */ struct cam_req_mgr_traverse { struct cam_req_mgr_traverse { Loading @@ -147,8 +144,6 @@ struct cam_req_mgr_traverse { struct cam_req_mgr_apply *apply_data; struct cam_req_mgr_apply *apply_data; struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_req_queue *in_q; bool validate_only; bool validate_only; bool self_link; bool inject_delay_chk; int32_t open_req_cnt; int32_t open_req_cnt; }; }; Loading Loading @@ -308,10 +303,6 @@ struct cam_req_mgr_connected_device { * notification to CRM at those hw events. * notification to CRM at those hw events. * @trigger_mask : mask on which irq the req is already applied * @trigger_mask : mask on which irq the req is already applied * @sync_link : pointer to the sync link for synchronization * @sync_link : pointer to the sync link for synchronization * @sof_counter : sof counter during sync_mode * @sync_self_ref : reference sync count against which the difference * between sync_counts for a given link is checked * @frame_skip_flag : flag that determines if a frame needs to be skipped * @sync_link_sof_skip : flag determines if a pkt is not available for a given * @sync_link_sof_skip : flag determines if a pkt is not available for a given * frame in a particular link skip corresponding * frame in a particular link skip corresponding * frame in sync link as well. * frame in sync link as well. Loading @@ -319,6 +310,10 @@ struct cam_req_mgr_connected_device { * to be serviced in the kernel. * to be serviced in the kernel. * @last_flush_id : Last request to flush * @last_flush_id : Last request to flush * @is_used : 1 if link is in use else 0 * @is_used : 1 if link is in use else 0 * @is_master : Based on pd among links, the link with the highest pd * is assigned as master * @initial_skip : Flag to determine if slave has started streaming in * master-slave sync * * */ */ struct cam_req_mgr_core_link { struct cam_req_mgr_core_link { Loading @@ -338,13 +333,12 @@ struct cam_req_mgr_core_link { uint32_t subscribe_event; uint32_t subscribe_event; uint32_t trigger_mask; uint32_t trigger_mask; struct cam_req_mgr_core_link *sync_link; struct cam_req_mgr_core_link *sync_link; int64_t sof_counter; int64_t sync_self_ref; bool frame_skip_flag; bool sync_link_sof_skip; bool sync_link_sof_skip; int32_t open_req_cnt; int32_t open_req_cnt; uint32_t last_flush_id; uint32_t last_flush_id; atomic_t is_used; atomic_t is_used; bool is_master; bool initial_skip; }; }; /** /** Loading Loading
drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c +304 −209 Original line number Original line Diff line number Diff line Loading @@ -43,9 +43,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->subscribe_event = 0; link->subscribe_event = 0; link->trigger_mask = 0; link->trigger_mask = 0; link->sync_link = 0; link->sync_link = 0; link->sof_counter = 0; link->sync_self_ref = 0; link->frame_skip_flag = false; link->sync_link_sof_skip = false; link->sync_link_sof_skip = false; link->open_req_cnt = 0; link->open_req_cnt = 0; link->last_flush_id = 0; link->last_flush_id = 0; Loading Loading @@ -143,31 +140,35 @@ static void __cam_req_mgr_dec_idx(int32_t *val, int32_t step, int32_t max_val) } } /** /** * __cam_req_mgr_validate_inject_delay() * __cam_req_mgr_inject_delay() * * * @brief : Check if any pd device is introducing inject delay * @brief : Check if any pd device is injecting delay * @tbl : cam_req_mgr_req_tbl * @tbl : cam_req_mgr_req_tbl * @curr_idx : slot idx * @curr_idx : slot idx * * * @return : 0 for success, negative for failure * @return : 0 for success, negative for failure */ */ static int __cam_req_mgr_validate_inject_delay( static int __cam_req_mgr_inject_delay( struct cam_req_mgr_req_tbl *tbl, struct cam_req_mgr_req_tbl *tbl, int32_t curr_idx) int32_t curr_idx) { { struct cam_req_mgr_tbl_slot *slot = NULL; struct cam_req_mgr_tbl_slot *slot = NULL; int rc = 0; while (tbl) { while (tbl) { slot = &tbl->slot[curr_idx]; slot = &tbl->slot[curr_idx]; if (slot->inject_delay > 0) { if (slot->inject_delay > 0) { slot->inject_delay--; slot->inject_delay--; return -EAGAIN; CAM_DBG(CAM_CRM, "Delay injected by pd %d device", tbl->pd); rc = -EAGAIN; } } __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta, tbl->num_slots); tbl->num_slots); tbl = tbl->next; tbl = tbl->next; } } return 0; return rc; } } /** /** Loading Loading @@ -209,19 +210,6 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data) tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status, traverse_data->in_q->slot[curr_idx].skip_idx); traverse_data->in_q->slot[curr_idx].skip_idx); if ((traverse_data->self_link == true) && (!traverse_data->inject_delay_chk)) { rc = __cam_req_mgr_validate_inject_delay(tbl, curr_idx); if (rc) { CAM_DBG(CAM_CRM, "Injecting Delay of one frame"); apply_data[tbl->pd].req_id = -1; /* This pd tbl not ready to proceed with asked idx */ SET_FAILURE_BIT(traverse_data->result, tbl->pd); return -EAGAIN; } traverse_data->inject_delay_chk = true; } /* Check if req is ready or in skip mode or pd tbl is in skip mode */ /* Check if req is ready or in skip mode or pd tbl is in skip mode */ if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY || if (tbl->slot[curr_idx].state == CRM_REQ_STATE_READY || traverse_data->in_q->slot[curr_idx].skip_idx == 1 || traverse_data->in_q->slot[curr_idx].skip_idx == 1 || Loading Loading @@ -552,14 +540,12 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link, * traversed through * traversed through * @idx : index within input request queue * @idx : index within input request queue * @validate_only : Whether to validate only and/or update settings * @validate_only : Whether to validate only and/or update settings * @self_link : To indicate whether the validation is for the given link or * other sync link * * * @return : 0 for success, negative for failure * @return : 0 for success, negative for failure * * */ */ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, int32_t idx, bool validate_only, bool self_link) int32_t idx, bool validate_only) { { int rc; int rc; struct cam_req_mgr_traverse traverse_data; struct cam_req_mgr_traverse traverse_data; Loading @@ -581,19 +567,16 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.in_q = in_q; traverse_data.in_q = in_q; traverse_data.result = 0; traverse_data.result = 0; traverse_data.validate_only = validate_only; traverse_data.validate_only = validate_only; traverse_data.self_link = self_link; traverse_data.inject_delay_chk = false; traverse_data.open_req_cnt = link->open_req_cnt; traverse_data.open_req_cnt = link->open_req_cnt; /* /* * Traverse through all pd tables, if result is success, * Traverse through all pd tables, if result is success, * apply the settings * apply the settings */ */ rc = __cam_req_mgr_traverse(&traverse_data); rc = __cam_req_mgr_traverse(&traverse_data); CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "SOF: idx %d self_link %d validate %d result %x pd_mask %x rc %d", "SOF: idx %d result %x pd_mask %x rc %d", idx, traverse_data.self_link, traverse_data.validate_only, idx, traverse_data.result, link->pd_mask, rc); traverse_data.result, link->pd_mask, rc); if (!rc && traverse_data.result == link->pd_mask) { if (!rc && traverse_data.result == link->pd_mask) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, Loading Loading @@ -642,113 +625,198 @@ static int32_t __cam_req_mgr_find_slot_for_req( } } /** /** * __cam_req_mgr_reset_sof_cnt() * __cam_req_mgr_check_sync_for_mslave() * * * @brief : the sof_count for both the links are reset * @brief : Processes requests during sync mode [master-slave] * @link : pointer to link whose input queue and req tbl are * Here master corresponds to the link having a higher * max_delay (pd) compared to the slave link. * @link : Pointer to link whose input queue and req tbl are * traversed through * traversed through * @slot : Pointer to the current slot being processed * @return : 0 for success, negative for failure * * */ */ static void __cam_req_mgr_reset_sof_cnt( static int __cam_req_mgr_check_sync_for_mslave( struct cam_req_mgr_core_link *link) struct cam_req_mgr_core_link *link, struct cam_req_mgr_slot *slot) { { link->sof_counter = -1; struct cam_req_mgr_core_link *sync_link = NULL; link->sync_link->sof_counter = -1; int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, rc = 0; link->frame_skip_flag = false; int64_t req_id = 0, sync_req_id = 0; if (!link->sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); return -EINVAL; } sync_link = link->sync_link; req_id = slot->req_id; CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link_hdl %x self_counter %lld other_counter %lld frame_skip_lag %d", "link_hdl %x req %lld frame_skip_flag %d ", link->link_hdl, link->sof_counter, link->link_hdl, req_id, link->sync_link_sof_skip); link->sync_link->sof_counter, link->frame_skip_flag); if (sync_link->sync_link_sof_skip) { CAM_DBG(CAM_CRM, "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; } } /** if (link->is_master) { * __cam_req_mgr_sof_cnt_initialize() rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); * if (rc) { * @brief : when the sof count is intially -1 it increments count CAM_DBG(CAM_CRM, * and computes the sync_self_ref for this link "Skip Process Req: %lld on link: %x", * the count needs to be wrapped back starting from 0 req_id, link->link_hdl); * @link : pointer to link whose input queue and req tbl are link->sync_link_sof_skip = true; * traversed through return rc; * } */ static void __cam_req_mgr_sof_cnt_initialize( struct cam_req_mgr_core_link *link) { link->sof_counter++; link->sync_self_ref = link->sof_counter - link->sync_link->sof_counter; if (sync_link->initial_skip) { CAM_DBG(CAM_CRM, "Link 0x%x [slave] not streamed on", sync_link->link_hdl); return -EAGAIN; } rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); if (rc) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link_hdl %x self_counter %lld other_counter %lld", "Req: %lld [master] not ready on link: %x, rc=%d", link->link_hdl, link->sof_counter, req_id, link->link_hdl, rc); link->sync_link->sof_counter); return rc; } } /** prev_idx = slot->idx; * __cam_req_mgr_wrap_sof_cnt() __cam_req_mgr_dec_idx(&prev_idx, * (link->max_delay - sync_link->max_delay), * @brief : once the sof count reaches a predefined maximum link->req.in_q->num_slots); * the count needs to be wrapped back starting from 0 * @link : pointer to link whose input queue and req tbl are rd_idx = sync_link->req.in_q->rd_idx; * traversed through sync_req_id = link->req.in_q->slot[prev_idx].req_id; * if (sync_req_id != -1) { */ sync_slot_idx = __cam_req_mgr_find_slot_for_req( static void __cam_req_mgr_wrap_sof_cnt( sync_link->req.in_q, sync_req_id); struct cam_req_mgr_core_link *link) { link->sof_counter = (MAX_SYNC_COUNT - (link->sync_link->sof_counter)); link->sync_link->sof_counter = 0; if (sync_slot_idx == -1) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link_hdl %x self_counter %lld sync_link_hdl %x other_counter %lld", "Prev Req: %lld [master] not found on link: %x [slave]", link->link_hdl, link->sof_counter, sync_req_id, sync_link->link_hdl); link->sync_link->link_hdl, link->sync_link->sof_counter); return -EINVAL; } } /** if ((sync_link->req.in_q->slot[sync_slot_idx].status != * __cam_req_mgr_validate_sof_cnt() CRM_SLOT_STATUS_REQ_APPLIED) && * ((sync_slot_idx - rd_idx) >= 1) && * @brief : validates sof count difference for a given link (sync_link->req.in_q->slot[rd_idx].status != * @link : pointer to link whose input queue and req tbl are CRM_SLOT_STATUS_REQ_APPLIED)) { * traversed through CAM_DBG(CAM_CRM, * @sync_link : pointer to the sync link "Prev Req: %lld [master] not next on link: %x [slave]", * @return : 0 for success, negative for failure sync_req_id, * sync_link->link_hdl); */ return -EINVAL; static int __cam_req_mgr_validate_sof_cnt( } struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_link *sync_link) { int64_t sync_diff = 0; int rc = 0; if (link->sof_counter == MAX_SYNC_COUNT) rc = __cam_req_mgr_check_link_is_ready(sync_link, __cam_req_mgr_wrap_sof_cnt(link); sync_slot_idx, true); if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Req: %lld not ready on [slave] link: %x, rc=%d", sync_req_id, sync_link->link_hdl, rc); return rc; } } } else { if (link->initial_skip) link->initial_skip = false; sync_diff = link->sof_counter - sync_link->sof_counter; sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, req_id); if (sync_slot_idx == -1) { CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [master]", req_id, sync_link->link_hdl); return -EINVAL; } if (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "link[%x] self_counter=%lld other_counter=%lld diff=%lld sync_self_ref=%lld", "Req: %lld [master] not applied yet: %x", link->link_hdl, link->sof_counter, req_id, sync_link->link_hdl); sync_link->sof_counter, sync_diff, link->sync_self_ref); return -EAGAIN; } if (sync_diff > SYNC_LINK_SOF_CNT_MAX_LMT) { rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); link->sync_link->frame_skip_flag = true; if (rc) { CAM_WARN(CAM_CRM, CAM_DBG(CAM_CRM, "Detected anomaly, skip link_hdl %x self_counter=%lld other_counter=%lld sync_self_ref=%lld", "Skip Process Req: %lld on link: %x", link->link_hdl, link->sof_counter, req_id, link->link_hdl); sync_link->sof_counter, link->sync_self_ref); link->sync_link_sof_skip = true; rc = -EPERM; return rc; } } next_idx = link->req.in_q->rd_idx; rd_idx = sync_link->req.in_q->rd_idx; __cam_req_mgr_inc_idx(&next_idx, (sync_link->max_delay - link->max_delay), link->req.in_q->num_slots); sync_req_id = link->req.in_q->slot[next_idx].req_id; sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, sync_req_id); if (sync_slot_idx == -1) { CAM_DBG(CAM_CRM, "Next Req: %lld [slave] not found on link: %x [master]", sync_req_id, sync_link->link_hdl); return -EINVAL; } if ((sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) && ((sync_slot_idx - rd_idx) >= 1) && (sync_link->req.in_q->slot[rd_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Next Req: %lld [slave] not next on link: %x [master]", sync_req_id, sync_link->link_hdl); return -EINVAL; } rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true); if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Next Req: %lld [slave] not ready on [master] link: %x, rc=%d", sync_req_id, sync_link->link_hdl, rc); return rc; return rc; } } } CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); /* * At this point all validation is successfully done * and we can proceed to apply the given request. * Ideally the next call should return success. */ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false); if (rc) CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc); return 0; } /** /** * __cam_req_mgr_process_sync_req() * __cam_req_mgr_check_sync_request_is_ready() * * * @brief : processes requests during sync mode * @brief : processes requests during sync mode * @link : pointer to link whose input queue and req tbl are * @link : pointer to link whose input queue and req tbl are Loading @@ -757,13 +825,13 @@ static int __cam_req_mgr_validate_sof_cnt( * @return : 0 for success, negative for failure * @return : 0 for success, negative for failure * * */ */ static int __cam_req_mgr_process_sync_req( static int __cam_req_mgr_check_sync_req_is_ready( struct cam_req_mgr_core_link *link, struct cam_req_mgr_core_link *link, struct cam_req_mgr_slot *slot) struct cam_req_mgr_slot *slot) { { struct cam_req_mgr_core_link *sync_link = NULL; struct cam_req_mgr_core_link *sync_link = NULL; int64_t req_id = 0; int64_t req_id = 0; int sync_slot_idx = 0, rc = 0; int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; if (!link->sync_link) { if (!link->sync_link) { CAM_ERR(CAM_CRM, "Sync link null"); CAM_ERR(CAM_CRM, "Sync link null"); Loading @@ -774,94 +842,82 @@ static int __cam_req_mgr_process_sync_req( req_id = slot->req_id; req_id = slot->req_id; CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, "link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld", "link_hdl %x req %lld frame_skip_flag %d ", link->link_hdl, req_id, link->sync_self_ref, link->sof_counter, link->link_hdl, req_id, link->sync_link_sof_skip); link->frame_skip_flag, link->sync_link->sync_self_ref); if (sync_link->sync_link_sof_skip) { if (sync_link->sync_link_sof_skip) { CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, "No req applied on corresponding SOF on sync link: %x", "No req applied on corresponding SOF on sync link: %x", sync_link->link_hdl); sync_link->link_hdl); sync_link->sync_link_sof_skip = false; sync_link->sync_link_sof_skip = false; /*It is to manage compensate inject delay for each pd*/ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true); return -EAGAIN; return -EINVAL; } } if (link->sof_counter == -1) { rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); __cam_req_mgr_sof_cnt_initialize(link); if (rc) { } else if ((link->frame_skip_flag) && CAM_DBG(CAM_CRM, (sync_link->sync_self_ref != -1)) { "Skip Process Req: %lld on link: %x", CAM_DBG(CAM_REQ, "Link[%x] Req[%lld] Resetting values ", req_id, link->link_hdl); link->link_hdl, req_id); link->sync_link_sof_skip = true; __cam_req_mgr_reset_sof_cnt(link); return rc; __cam_req_mgr_sof_cnt_initialize(link); } else { link->sof_counter++; } } rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true); rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true); if (rc) { if (rc) { CAM_DBG(CAM_REQ, CAM_DBG(CAM_CRM, "Req: %lld [My link] not ready on link: %x, rc=%d", "Req: %lld [My link] not ready on link: %x, rc=%d", req_id, link->link_hdl, rc); req_id, link->link_hdl, rc); link->sync_link_sof_skip = true; link->sync_link_sof_skip = true; goto failure; return rc; } } sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_slot_idx = __cam_req_mgr_find_slot_for_req( sync_link->req.in_q, req_id); sync_link->req.in_q, req_id); if (sync_slot_idx == -1) { if (sync_slot_idx != -1) { CAM_DBG(CAM_CRM, "Req: %lld not found on link: %x [other link]", rc = __cam_req_mgr_check_link_is_ready( req_id, sync_link->link_hdl); sync_link, sync_slot_idx, true, false); link->sync_link_sof_skip = true; CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d", return -EINVAL; sync_slot_idx, sync_link->req.in_q->slot[sync_slot_idx].status, rc); } else { CAM_DBG(CAM_CRM, "sync_slot_idx=%d, rc=%d", sync_slot_idx, rc); } } if ((sync_slot_idx != -1) && sync_rd_idx = sync_link->req.in_q->rd_idx; ((sync_link->req.in_q->slot[sync_slot_idx].status == if ((sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) { CRM_SLOT_STATUS_REQ_APPLIED) && rc = __cam_req_mgr_validate_sof_cnt(link, sync_link); ((sync_slot_idx - sync_rd_idx) >= 1) && if (rc) { (sync_link->req.in_q->slot[sync_rd_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, CAM_DBG(CAM_CRM, "Req: %lld validate failed: %x", "Req: %lld [other link] not next req to be applied on link: %x", req_id, sync_link->link_hdl); req_id, sync_link->link_hdl); goto failure; link->sync_link_sof_skip = true; return -EAGAIN; } rc = __cam_req_mgr_check_link_is_ready(sync_link, sync_slot_idx, true); if (rc && (sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Req: %lld not ready on [other link] link: %x, rc=%d", req_id, sync_link->link_hdl, rc); link->sync_link_sof_skip = true; return rc; } } CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); req_id, link->link_hdl); /* /* * At this point all validation is successfully done * At this point all validation is successfully done * and we can proceed to apply the given request. * and we can proceed to apply the given request. * Ideally the next call should return success. * Ideally the next call should return success. */ */ rc = __cam_req_mgr_check_link_is_ready(link, rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false); slot->idx, false, true); if (rc) if (rc) CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc); CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc); } else { CAM_DBG(CAM_REQ, "Req: %lld [Other link] not ready to apply on link: %x", req_id, sync_link->link_hdl); rc = -EPERM; link->sync_link_sof_skip = true; goto failure; } return rc; failure: return 0; link->sof_counter--; return rc; } } /** /** Loading Loading @@ -922,11 +978,21 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, goto error; goto error; } } if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) && rc = __cam_req_mgr_process_sync_req(link, slot); (link->sync_link)) { if (link->is_master || link->sync_link->is_master) rc = __cam_req_mgr_check_sync_for_mslave( link, slot); else else rc = __cam_req_mgr_check_sync_req_is_ready( link, slot); } else { rc = __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); if (!rc) rc = __cam_req_mgr_check_link_is_ready(link, rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, false, true); slot->idx, false); } if (rc < 0) { if (rc < 0) { /* /* Loading Loading @@ -970,9 +1036,6 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } } spin_unlock_bh(&link->link_state_spin_lock); spin_unlock_bh(&link->link_state_spin_lock); if (link->sync_link_sof_skip) link->sync_link_sof_skip = false; if (link->trigger_mask == link->subscribe_event) { if (link->trigger_mask == link->subscribe_event) { slot->status = CRM_SLOT_STATUS_REQ_APPLIED; slot->status = CRM_SLOT_STATUS_REQ_APPLIED; link->trigger_mask = 0; link->trigger_mask = 0; Loading Loading @@ -1481,21 +1544,14 @@ static void __cam_req_mgr_unreserve_link( for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i] == link) if (session->links[i] == link) session->links[i] = NULL; session->links[i] = NULL; } if ((session->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC) && if (link->sync_link) { (link->sync_link)) { if (link->sync_link == session->links[i]) /* * make sure to unlink sync setup under the assumption * of only having 2 links in a given session */ session->sync_mode = CAM_REQ_MGR_SYNC_MODE_NO_SYNC; for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) { if (session->links[i]) session->links[i]->sync_link = NULL; session->links[i]->sync_link = NULL; } } } } link->sync_link = NULL; session->num_links--; session->num_links--; CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links); mutex_unlock(&session->lock); mutex_unlock(&session->lock); Loading Loading @@ -1769,8 +1825,9 @@ int cam_req_mgr_process_add_req(void *priv, void *data) trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device); if (slot->req_ready_map == tbl->dev_mask) { if (slot->req_ready_map == tbl->dev_mask) { CAM_DBG(CAM_REQ, "idx %d req_id %lld pd %d SLOT READY", CAM_DBG(CAM_REQ, idx, add_req->req_id, tbl->pd); "link 0x%x idx %d req_id %lld pd %d SLOT READY", link->link_hdl, idx, add_req->req_id, tbl->pd); slot->state = CRM_REQ_STATE_READY; slot->state = CRM_REQ_STATE_READY; } } mutex_unlock(&link->req.lock); mutex_unlock(&link->req.lock); Loading Loading @@ -2673,6 +2730,33 @@ int cam_req_mgr_schedule_request( return rc; return rc; } } /** * __cam_req_mgr_set_master_link() * * @brief : Each links sets its max pd delay based on the devices on the * link. The link with higher pd is assigned master. * @link1 : One of the sync links * @link2 : The other sync link */ static void __cam_req_mgr_set_master_link( struct cam_req_mgr_core_link *link1, struct cam_req_mgr_core_link *link2) { if (link1->max_delay > link2->max_delay) { link1->is_master = true; link2->initial_skip = true; } else if (link2->max_delay > link1->max_delay) { link2->is_master = true; link1->initial_skip = true; } CAM_DBG(CAM_CRM, "link_hdl1[0x%x] is_master [%u] link_hdl2[0x%x] is_master[%u]", link1->link_hdl, link1->is_master, link2->link_hdl, link2->is_master); } int cam_req_mgr_sync_config( int cam_req_mgr_sync_config( struct cam_req_mgr_sync_mode *sync_info) struct cam_req_mgr_sync_mode *sync_info) { { Loading @@ -2693,6 +2777,12 @@ int cam_req_mgr_sync_config( return -EINVAL; return -EINVAL; } } if ((sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_SYNC) && (sync_info->sync_mode != CAM_REQ_MGR_SYNC_MODE_NO_SYNC)) { CAM_ERR(CAM_CRM, "Invalid sync mode %d", sync_info->sync_mode); return -EINVAL; } if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) { if ((!sync_info->link_hdls[0]) || (!sync_info->link_hdls[1])) { CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x", CAM_WARN(CAM_CRM, "Invalid link handles 0x%x 0x%x", sync_info->link_hdls[0], sync_info->link_hdls[1]); sync_info->link_hdls[0], sync_info->link_hdls[1]); Loading Loading @@ -2729,17 +2819,22 @@ int cam_req_mgr_sync_config( goto done; goto done; } } link1->sof_counter = -1; link1->sync_self_ref = -1; link1->frame_skip_flag = false; link1->sync_link_sof_skip = false; link1->sync_link_sof_skip = false; link1->sync_link = link2; link1->sync_link = NULL; link2->sof_counter = -1; link2->sync_self_ref = -1; link2->frame_skip_flag = false; link2->sync_link_sof_skip = false; link2->sync_link_sof_skip = false; link2->sync_link = NULL; link1->is_master = false; link2->is_master = false; link1->initial_skip = false; link2->initial_skip = false; if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) { link1->sync_link = link2; link2->sync_link = link1; link2->sync_link = link1; __cam_req_mgr_set_master_link(link1, link2); } cam_session->sync_mode = sync_info->sync_mode; cam_session->sync_mode = sync_info->sync_mode; CAM_DBG(CAM_REQ, CAM_DBG(CAM_REQ, Loading
drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h +6 −12 Original line number Original line Diff line number Diff line Loading @@ -135,9 +135,6 @@ enum cam_req_mgr_link_state { * @apply_data : pointer which various tables will update during traverse * @apply_data : pointer which various tables will update during traverse * @in_q : input request queue pointer * @in_q : input request queue pointer * @validate_only : Whether to validate only and/or update settings * @validate_only : Whether to validate only and/or update settings * @self_link : To indicate whether the check is for the given link or * the other sync link * @inject_delay_chk : if inject delay has been validated for all pd devices * @open_req_cnt : Count of open requests yet to be serviced in the kernel. * @open_req_cnt : Count of open requests yet to be serviced in the kernel. */ */ struct cam_req_mgr_traverse { struct cam_req_mgr_traverse { Loading @@ -147,8 +144,6 @@ struct cam_req_mgr_traverse { struct cam_req_mgr_apply *apply_data; struct cam_req_mgr_apply *apply_data; struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_req_queue *in_q; bool validate_only; bool validate_only; bool self_link; bool inject_delay_chk; int32_t open_req_cnt; int32_t open_req_cnt; }; }; Loading Loading @@ -308,10 +303,6 @@ struct cam_req_mgr_connected_device { * notification to CRM at those hw events. * notification to CRM at those hw events. * @trigger_mask : mask on which irq the req is already applied * @trigger_mask : mask on which irq the req is already applied * @sync_link : pointer to the sync link for synchronization * @sync_link : pointer to the sync link for synchronization * @sof_counter : sof counter during sync_mode * @sync_self_ref : reference sync count against which the difference * between sync_counts for a given link is checked * @frame_skip_flag : flag that determines if a frame needs to be skipped * @sync_link_sof_skip : flag determines if a pkt is not available for a given * @sync_link_sof_skip : flag determines if a pkt is not available for a given * frame in a particular link skip corresponding * frame in a particular link skip corresponding * frame in sync link as well. * frame in sync link as well. Loading @@ -319,6 +310,10 @@ struct cam_req_mgr_connected_device { * to be serviced in the kernel. * to be serviced in the kernel. * @last_flush_id : Last request to flush * @last_flush_id : Last request to flush * @is_used : 1 if link is in use else 0 * @is_used : 1 if link is in use else 0 * @is_master : Based on pd among links, the link with the highest pd * is assigned as master * @initial_skip : Flag to determine if slave has started streaming in * master-slave sync * * */ */ struct cam_req_mgr_core_link { struct cam_req_mgr_core_link { Loading @@ -338,13 +333,12 @@ struct cam_req_mgr_core_link { uint32_t subscribe_event; uint32_t subscribe_event; uint32_t trigger_mask; uint32_t trigger_mask; struct cam_req_mgr_core_link *sync_link; struct cam_req_mgr_core_link *sync_link; int64_t sof_counter; int64_t sync_self_ref; bool frame_skip_flag; bool sync_link_sof_skip; bool sync_link_sof_skip; int32_t open_req_cnt; int32_t open_req_cnt; uint32_t last_flush_id; uint32_t last_flush_id; atomic_t is_used; atomic_t is_used; bool is_master; bool initial_skip; }; }; /** /** Loading