Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef0cd84c authored by Karthik Anantha Ram's avatar Karthik Anantha Ram
Browse files

msm: camera: reqmgr: Adds total ordering of reqs for all pd devices



For any pd request to be applied - all the lower pd devices need to be
ready. So lowest will always go through, then the next higher if ready
will go through. Requests to lower pd devices should not be blocked
if next higher is not ready.

Change-Id: I4f1232135371c2025bfe9e9a9dace76a286585fb
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
parent 00f1431b
Loading
Loading
Loading
Loading
+116 −43
Original line number Original line Diff line number Diff line
@@ -25,23 +25,6 @@


static struct cam_req_mgr_core_device *g_crm_core_dev;
static struct cam_req_mgr_core_device *g_crm_core_dev;



void cam_req_mgr_handle_core_shutdown(void)
{
	struct cam_req_mgr_core_session *session;
	struct cam_req_mgr_core_session *tsession;
	struct cam_req_mgr_session_info ses_info;

	if (!list_empty(&g_crm_core_dev->session_head)) {
		list_for_each_entry_safe(session, tsession,
			&g_crm_core_dev->session_head, entry) {
			ses_info.session_hdl =
				session->session_hdl;
			cam_req_mgr_destroy_session(&ses_info);
		}
	}
}

static int __cam_req_mgr_setup_payload(struct cam_req_mgr_core_workq *workq)
static int __cam_req_mgr_setup_payload(struct cam_req_mgr_core_workq *workq)
{
{
	int32_t                  i = 0;
	int32_t                  i = 0;
@@ -202,11 +185,18 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)


	if (tbl->inject_delay > 0 && (traverse_data->validate_only == false)) {
	if (tbl->inject_delay > 0 && (traverse_data->validate_only == false)) {
		CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
		CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
		apply_data[tbl->pd].req_id = -1;
		tbl->inject_delay--;
		tbl->inject_delay--;
		/* This pd table is not ready to proceed with asked idx */
		/* This pd table is not ready to proceed with asked idx */
		SET_FAILURE_BIT(traverse_data->result, tbl->pd);
		SET_FAILURE_BIT(traverse_data->result, tbl->pd);
		return -EAGAIN;
		apply_data[tbl->pd].req_id = -1;
		if (tbl->next) {
			__cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta,
				tbl->num_slots);
			traverse_data->idx = next_idx;
			traverse_data->tbl = tbl->next;
			rc = __cam_req_mgr_traverse(traverse_data);
		}
		return rc;
	}
	}


	/* 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 */
@@ -241,8 +231,20 @@ static int __cam_req_mgr_traverse(struct cam_req_mgr_traverse *traverse_data)
		}
		}
	} else {
	} else {
		/* This pd table is not ready to proceed with asked idx */
		/* This pd table is not ready to proceed with asked idx */
		if (tbl->slot[curr_idx].state == CRM_REQ_STATE_APPLIED)
			SET_SUCCESS_BIT(traverse_data->result, tbl->pd);
		else
			SET_FAILURE_BIT(traverse_data->result, tbl->pd);
			SET_FAILURE_BIT(traverse_data->result, tbl->pd);
		return -EAGAIN;

		apply_data[tbl->pd].req_id = -1;
		if (tbl->next) {
			__cam_req_mgr_dec_idx(&next_idx, tbl->pd_delta,
				tbl->num_slots);
			traverse_data->idx = next_idx;
			traverse_data->tbl = tbl->next;
			rc = __cam_req_mgr_traverse(traverse_data);
		}
		return rc;
	}
	}
	return 0;
	return 0;
}
}
@@ -472,12 +474,14 @@ 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
 * @result        : Holds the value that indicates which of the pd
 *                  tables have a req that is ready to be applied
 *
 *
 * @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)
	int32_t idx, bool validate_only, int *result)
{
{
	int                            rc;
	int                            rc;
	struct cam_req_mgr_traverse    traverse_data;
	struct cam_req_mgr_traverse    traverse_data;
@@ -508,15 +512,18 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
	CAM_DBG(CAM_CRM, "SOF: idx %d result %x pd_mask %x rc %d",
	CAM_DBG(CAM_CRM, "SOF: idx %d result %x pd_mask %x rc %d",
		idx, traverse_data.result, link->pd_mask, rc);
		idx, traverse_data.result, link->pd_mask, rc);


	if (!rc && traverse_data.result == link->pd_mask) {
	if (!traverse_data.result)
		return -EAGAIN;

	if (!rc) {
		CAM_DBG(CAM_CRM,
		CAM_DBG(CAM_CRM,
			"APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
			"APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
			link->link_hdl, idx,
			link->link_hdl, idx,
			apply_data[2].req_id, apply_data[1].req_id,
			apply_data[2].req_id, apply_data[1].req_id,
			apply_data[0].req_id);
			apply_data[0].req_id);
	} else
	}
		rc = -EAGAIN;


	*result = traverse_data.result;
	return rc;
	return rc;
}
}


@@ -645,12 +652,16 @@ static int __cam_req_mgr_validate_sof_cnt(
 * @link     : pointer to link whose input queue and req tbl are
 * @link     : pointer to link whose input queue and req tbl are
 *             traversed through
 *             traversed through
 * @slot     : pointer to the current slot being processed
 * @slot     : pointer to the current slot being processed
 * @result   : Holds the value that indicates which of the pd
 *             tables have a req that is ready to be applied
 *
 * @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_process_sync_req(
	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,
	int *result)
{
{
	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;
@@ -675,7 +686,7 @@ static int __cam_req_mgr_process_sync_req(
		link->sof_counter++;
		link->sof_counter++;
	}
	}


	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true);
	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, result);
	if (rc) {
	if (rc) {
		CAM_DBG(CAM_CRM,
		CAM_DBG(CAM_CRM,
			"Req: %lld [My link]not available link: %x, rc=%d",
			"Req: %lld [My link]not available link: %x, rc=%d",
@@ -687,7 +698,7 @@ static int __cam_req_mgr_process_sync_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) {
		rc = __cam_req_mgr_check_link_is_ready(
		rc = __cam_req_mgr_check_link_is_ready(
			sync_link, sync_slot_idx, true);
			sync_link, sync_slot_idx, true, result);
		CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
		CAM_DBG(CAM_CRM, "sync_slot_idx=%d, status=%d, rc=%d",
			sync_slot_idx,
			sync_slot_idx,
			sync_link->req.in_q->slot[sync_slot_idx].status,
			sync_link->req.in_q->slot[sync_slot_idx].status,
@@ -707,7 +718,8 @@ static int __cam_req_mgr_process_sync_req(
				req_id, sync_link->link_hdl);
				req_id, sync_link->link_hdl);
			goto failure;
			goto failure;
		}
		}
		__cam_req_mgr_check_link_is_ready(link, slot->idx, false);
		__cam_req_mgr_check_link_is_ready(link, slot->idx, false,
			result);
	} else {
	} else {
		CAM_DBG(CAM_CRM,
		CAM_DBG(CAM_CRM,
			"Req: %lld [Other link] not ready to apply on link: %x",
			"Req: %lld [Other link] not ready to apply on link: %x",
@@ -723,6 +735,41 @@ static int __cam_req_mgr_process_sync_req(
	return rc;
	return rc;
}
}


/**
 * __cam_req_mgr_reset_pd_tables()
 *
 * @brief    : resets pd tables based on req getting applied on
 *             from a particular pd table
 * @link     : pointer to link whose input queue and req tbl are
 *             traversed through
 * @slot     : Pointer to the current slot
 * @result   : indicates request of which pd table was successfully
 *             processed
 *
 */
static void __cam_req_mgr_reset_pd_tables(
	struct cam_req_mgr_core_link *link,
	struct cam_req_mgr_slot *slot,
	int result)
{
	int pd_set_bit = 0;
	int curr_idx = slot->idx;
	int no_tables = link->req.num_tbl;
	int max_pd_delay = link->max_delay;
	struct cam_req_mgr_req_tbl  *tbl = link->req.l_tbl;
	struct cam_req_mgr_req_queue *in_q = link->req.in_q;

	while (no_tables) {
		pd_set_bit = (result & (1 << max_pd_delay));
		if (pd_set_bit)
			tbl->slot[curr_idx].state = CRM_REQ_STATE_APPLIED;
		max_pd_delay--;
		no_tables--;
		tbl = tbl->next;
		__cam_req_mgr_dec_idx(&curr_idx, 1, in_q->num_slots);
	}
}

/**
/**
 * __cam_req_mgr_process_req()
 * __cam_req_mgr_process_req()
 *
 *
@@ -736,7 +783,7 @@ static int __cam_req_mgr_process_sync_req(
static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
	uint32_t trigger)
	uint32_t trigger)
{
{
	int                                  rc = 0, idx;
	int                                  rc = 0, idx, result = 0;
	struct cam_req_mgr_slot             *slot = NULL;
	struct cam_req_mgr_slot             *slot = NULL;
	struct cam_req_mgr_req_queue        *in_q;
	struct cam_req_mgr_req_queue        *in_q;
	struct cam_req_mgr_core_session     *session;
	struct cam_req_mgr_core_session     *session;
@@ -782,10 +829,11 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
		}
		}


		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);
			rc = __cam_req_mgr_process_sync_req(link, slot,
				&result);
		else
		else
			rc = __cam_req_mgr_check_link_is_ready(link,
			rc = __cam_req_mgr_check_link_is_ready(link,
				slot->idx, false);
				slot->idx, false, &result);


		if (rc < 0) {
		if (rc < 0) {
			/*
			/*
@@ -830,16 +878,25 @@ 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->trigger_mask == link->subscribe_event) {
		if (link->trigger_mask == link->subscribe_event) {
			if (result == link->pd_mask) {
				slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
				slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
			link->trigger_mask = 0;
				CAM_DBG(CAM_CRM, "req %d is applied on link %d",
				CAM_DBG(CAM_CRM, "req %d is applied on link %d",
				slot->req_id,
					slot->req_id, link->link_hdl);
				link->link_hdl);
				idx = in_q->rd_idx;
				idx = in_q->rd_idx;
				__cam_req_mgr_dec_idx(
				__cam_req_mgr_dec_idx(
					&idx, link->max_delay + 1,
					&idx, link->max_delay + 1,
					in_q->num_slots);
					in_q->num_slots);
				__cam_req_mgr_reset_req_slot(link, idx);
				__cam_req_mgr_reset_req_slot(link, idx);
			} else {
				CAM_DBG(CAM_CRM,
					"Req:%lld not applied on all devices",
				slot->req_id);
				__cam_req_mgr_reset_pd_tables(link, slot,
					result);
				slot->status = CRM_SLOT_STATUS_REQ_PENDING;
			}

			link->trigger_mask = 0;
		}
		}
	}
	}
	mutex_unlock(&session->lock);
	mutex_unlock(&session->lock);
@@ -2028,6 +2085,22 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
	return rc;
	return rc;
}
}


void cam_req_mgr_handle_core_shutdown(void)
{
	struct cam_req_mgr_core_session *session;
	struct cam_req_mgr_core_session *tsession;
	struct cam_req_mgr_session_info ses_info;

	if (!list_empty(&g_crm_core_dev->session_head)) {
		list_for_each_entry_safe(session, tsession,
			&g_crm_core_dev->session_head, entry) {
			ses_info.session_hdl =
				session->session_hdl;
			cam_req_mgr_destroy_session(&ses_info);
		}
	}
}

/* IOCTLs handling section */
/* IOCTLs handling section */
int cam_req_mgr_create_session(
int cam_req_mgr_create_session(
	struct cam_req_mgr_session_info *ses_info)
	struct cam_req_mgr_session_info *ses_info)
+2 −0
Original line number Original line Diff line number Diff line
@@ -79,12 +79,14 @@ struct crm_task_payload {
 * EMPTY   : indicates req slot is empty
 * EMPTY   : indicates req slot is empty
 * PENDING : indicates req slot is waiting for reqs from all devs
 * PENDING : indicates req slot is waiting for reqs from all devs
 * READY   : indicates req slot is ready to be sent to devs
 * READY   : indicates req slot is ready to be sent to devs
 * APPLIED : indicates req slot is already sent to devs
 * INVALID : indicates req slot is not in valid state
 * INVALID : indicates req slot is not in valid state
 */
 */
enum crm_req_state {
enum crm_req_state {
	CRM_REQ_STATE_EMPTY,
	CRM_REQ_STATE_EMPTY,
	CRM_REQ_STATE_PENDING,
	CRM_REQ_STATE_PENDING,
	CRM_REQ_STATE_READY,
	CRM_REQ_STATE_READY,
	CRM_REQ_STATE_APPLIED,
	CRM_REQ_STATE_INVALID,
	CRM_REQ_STATE_INVALID,
};
};