Pārlūkot izejas kodu

Merge "msm: camera: req_mgr: Support for 3 links in CRM" into camera-kernel.lnx.4.0

Haritha Chintalapati 5 gadi atpakaļ
vecāks
revīzija
f91e158abf

+ 138 - 123
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -22,6 +22,7 @@ static struct cam_req_mgr_core_link g_links[MAXIMUM_LINKS_PER_SESSION];
 void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 {
 	uint32_t pd = 0;
+	int i = 0;
 
 	link->link_hdl = 0;
 	link->num_devs = 0;
@@ -37,7 +38,6 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 	link->parent = NULL;
 	link->subscribe_event = 0;
 	link->trigger_mask = 0;
-	link->sync_link = 0;
 	link->sync_link_sof_skip = false;
 	link->open_req_cnt = 0;
 	link->last_flush_id = 0;
@@ -52,12 +52,16 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 	link->sof_timestamp = 0;
 	link->prev_sof_timestamp = 0;
 	link->skip_init_frame = false;
+	link->num_sync_links = 0;
 	atomic_set(&link->eof_event_cnt, 0);
 
 	for (pd = 0; pd < CAM_PIPELINE_DELAY_MAX; pd++) {
 		link->req.apply_data[pd].req_id = -1;
 		link->req.prev_apply_data[pd].req_id = -1;
 	}
+
+	for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++)
+		link->sync_link[i] = NULL;
 }
 
 void cam_req_mgr_handle_core_shutdown(void)
@@ -1100,20 +1104,19 @@ static int32_t __cam_req_mgr_find_slot_for_req(
  */
 static int __cam_req_mgr_check_sync_for_mslave(
 	struct cam_req_mgr_core_link *link,
+	struct cam_req_mgr_core_link *sync_link,
 	struct cam_req_mgr_slot *slot)
 {
-	struct cam_req_mgr_core_link *sync_link = NULL;
 	struct cam_req_mgr_slot      *sync_slot = NULL;
 	int sync_slot_idx = 0, prev_idx, next_idx, rd_idx, sync_rd_idx, rc = 0;
 	int64_t req_id = 0, sync_req_id = 0;
 	int32_t sync_num_slots = 0;
 
-	if (!link->sync_link) {
+	if (!sync_link) {
 		CAM_ERR(CAM_CRM, "Sync link null");
 		return -EINVAL;
 	}
 
-	sync_link = link->sync_link;
 	req_id = slot->req_id;
 	sync_num_slots = sync_link->req.in_q->num_slots;
 	sync_rd_idx = sync_link->req.in_q->rd_idx;
@@ -1288,15 +1291,6 @@ static int __cam_req_mgr_check_sync_for_mslave(
 		"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;
 }
 
@@ -1313,9 +1307,9 @@ static int __cam_req_mgr_check_sync_for_mslave(
  */
 static int __cam_req_mgr_check_sync_req_is_ready(
 	struct cam_req_mgr_core_link *link,
+	struct cam_req_mgr_core_link *sync_link,
 	struct cam_req_mgr_slot *slot)
 {
-	struct cam_req_mgr_core_link *sync_link = NULL;
 	struct cam_req_mgr_slot *sync_rd_slot = NULL;
 	int64_t req_id = 0, sync_req_id = 0;
 	int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0;
@@ -1325,12 +1319,11 @@ static int __cam_req_mgr_check_sync_req_is_ready(
 	uint64_t master_slave_diff = 0;
 	bool ready = true, sync_ready = true;
 
-	if (!link->sync_link) {
+	if (!sync_link) {
 		CAM_ERR(CAM_CRM, "Sync link null");
 		return -EINVAL;
 	}
 
-	sync_link = link->sync_link;
 	req_id = slot->req_id;
 	sync_num_slots = sync_link->req.in_q->num_slots;
 	sync_rd_idx = sync_link->req.in_q->rd_idx;
@@ -1520,6 +1513,50 @@ static int __cam_req_mgr_check_sync_req_is_ready(
 		"Req: %lld ready to apply on link: %x [validation successful]",
 		req_id, link->link_hdl);
 
+	return 0;
+}
+
+static int __cam_req_mgr_check_multi_sync_link_ready(
+	struct cam_req_mgr_core_link *link,
+	struct cam_req_mgr_slot *slot)
+{
+	int i, rc = 0;
+
+	for (i = 0; i < link->num_sync_links; i++) {
+		if (link->sync_link[i]) {
+			if (link->max_delay == link->sync_link[i]->max_delay) {
+				rc = __cam_req_mgr_check_sync_req_is_ready(
+						link, link->sync_link[i], slot);
+				if (rc < 0) {
+					CAM_DBG(CAM_CRM, "link %x not ready",
+						link->link_hdl);
+					return rc;
+				}
+			} else if (link->max_delay >
+					link->sync_link[i]->max_delay) {
+				link->is_master = true;
+				link->sync_link[i]->is_master = false;
+				rc = __cam_req_mgr_check_sync_for_mslave(
+					link, link->sync_link[i], slot);
+				if (rc < 0) {
+					CAM_DBG(CAM_CRM, "link%x not ready",
+						link->link_hdl);
+					return rc;
+				}
+			} else {
+				link->is_master = false;
+				link->sync_link[i]->is_master = true;
+				rc = __cam_req_mgr_check_sync_for_mslave(
+						link, link->sync_link[i], slot);
+				if (rc < 0) {
+					CAM_DBG(CAM_CRM, "link %x not ready",
+						link->link_hdl);
+					return rc;
+				}
+			}
+		}
+	}
+
 	/*
 	 *  At this point all validation is successfully done
 	 *  and we can proceed to apply the given request.
@@ -1545,13 +1582,14 @@ static int __cam_req_mgr_check_sync_req_is_ready(
 static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 	struct cam_req_mgr_trigger_notify *trigger_data)
 {
-	int                                  rc = 0, idx;
+	int                                  rc = 0, idx, i;
 	int                                  reset_step = 0;
 	uint32_t                             trigger = trigger_data->trigger;
 	struct cam_req_mgr_slot             *slot = NULL;
 	struct cam_req_mgr_req_queue        *in_q;
 	struct cam_req_mgr_core_session     *session;
 	struct cam_req_mgr_connected_device *dev;
+	struct cam_req_mgr_core_link        *tmp_link = NULL;
 
 	in_q = link->req.in_q;
 	session = (struct cam_req_mgr_core_session *)link->parent;
@@ -1602,22 +1640,9 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 			goto error;
 		}
 
-		if ((slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) &&
-			(link->sync_link)) {
-			if (link->is_master || link->sync_link->is_master) {
-				if (!link->in_msync_mode) {
-					CAM_DBG(CAM_CRM,
-						"Settings master-slave sync mode for link 0x%x",
-						link->link_hdl);
-					link->in_msync_mode = true;
-				}
-
-				rc =  __cam_req_mgr_check_sync_for_mslave(
-					link, slot);
-			} else {
-				rc = __cam_req_mgr_check_sync_req_is_ready(
-					link, slot);
-			}
+		if (slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
+			rc = __cam_req_mgr_check_multi_sync_link_ready(
+				link, slot);
 		} else {
 			if (link->in_msync_mode) {
 				CAM_DBG(CAM_CRM,
@@ -1625,9 +1650,12 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 					link->link_hdl);
 				link->in_msync_mode = false;
 				link->initial_sync_req = -1;
-				if (link->sync_link) {
-					link->sync_link->initial_sync_req = -1;
-					link->sync_link->in_msync_mode = false;
+				for (i = 0; i < link->num_sync_links; i++) {
+					if (link->sync_link[i]) {
+						tmp_link = link->sync_link[i];
+						tmp_link->initial_sync_req = -1;
+						tmp_link->in_msync_mode = false;
+					}
 				}
 			}
 
@@ -1715,11 +1743,15 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 				link->link_hdl);
 			idx = in_q->rd_idx;
 			reset_step = link->max_delay;
-			if (link->sync_link) {
-				if ((link->in_msync_mode) &&
-					(link->sync_link->is_master))
-					reset_step =
-						link->sync_link->max_delay;
+
+			for (i = 0; i < link->num_sync_links; i++) {
+				if (link->sync_link[i]) {
+					if ((link->in_msync_mode) &&
+						(link->sync_link[i]->max_delay >
+							reset_step))
+						reset_step =
+						link->sync_link[i]->max_delay;
+				}
 			}
 
 			if (slot->req_id > 0)
@@ -2160,7 +2192,10 @@ static struct cam_req_mgr_core_link *__cam_req_mgr_reserve_link(
 	in_q->num_slots = 0;
 	link->state = CAM_CRM_LINK_STATE_IDLE;
 	link->parent = (void *)session;
-	link->sync_link = NULL;
+
+	for (i = 0; i < MAXIMUM_LINKS_PER_SESSION - 1; i++)
+		link->sync_link[i] = NULL;
+
 	mutex_unlock(&link->lock);
 
 	mutex_lock(&session->lock);
@@ -2223,7 +2258,7 @@ static void __cam_req_mgr_unreserve_link(
 	struct cam_req_mgr_core_session *session,
 	struct cam_req_mgr_core_link *link)
 {
-	int i;
+	int i, j;
 
 	if (!session || !link) {
 		CAM_ERR(CAM_CRM, "NULL session/link ptr %pK %pK",
@@ -2242,14 +2277,16 @@ static void __cam_req_mgr_unreserve_link(
 	for (i = 0; i < MAXIMUM_LINKS_PER_SESSION; i++) {
 		if (session->links[i] == link)
 			session->links[i] = NULL;
-
-		if (link->sync_link) {
-			if (link->sync_link == session->links[i])
-				session->links[i]->sync_link = NULL;
+		for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++) {
+			if (link->sync_link[j]) {
+				if (link->sync_link[j] == session->links[i])
+					session->links[i]->sync_link[j] = NULL;
+			}
 		}
 	}
 
-	link->sync_link = NULL;
+	for (j = 0; j < MAXIMUM_LINKS_PER_SESSION - 1; j++)
+		link->sync_link[j] = NULL;
 	session->num_links--;
 	CAM_DBG(CAM_CRM, "Active session links (%d)", session->num_links);
 	mutex_unlock(&session->lock);
@@ -2361,7 +2398,7 @@ end:
  */
 int cam_req_mgr_process_sched_req(void *priv, void *data)
 {
-	int                               rc = 0;
+	int                               rc = 0, i;
 	struct cam_req_mgr_sched_request *sched_req = NULL;
 	struct cam_req_mgr_core_link     *link = NULL;
 	struct cam_req_mgr_req_queue     *in_q = NULL;
@@ -2421,8 +2458,10 @@ int cam_req_mgr_process_sched_req(void *priv, void *data)
 			link->initial_sync_req = slot->req_id;
 	} else {
 		link->initial_sync_req = -1;
-		if (link->sync_link)
-			link->sync_link->initial_sync_req = -1;
+		for (i = 0; i < link->num_sync_links; i++) {
+			if (link->sync_link[i])
+				link->sync_link[i]->initial_sync_req = -1;
+		}
 	}
 
 	mutex_unlock(&link->req.lock);
@@ -2655,7 +2694,7 @@ int cam_req_mgr_process_error(void *priv, void *data)
 			__cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
 			in_q->rd_idx = idx;
 			in_q->slot[idx].status = CRM_SLOT_STATUS_REQ_ADDED;
-			if (link->sync_link) {
+			if (link->sync_link[0]) {
 				in_q->slot[idx].sync_mode = 0;
 				__cam_req_mgr_inc_idx(&idx, 1,
 					link->req.l_tbl->num_slots);
@@ -3897,40 +3936,13 @@ end:
 	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(
 	struct cam_req_mgr_sync_mode *sync_info)
 {
-	int                              rc = 0;
+	int                              i, j, rc = 0;
+	int                              sync_idx = 0;
 	struct cam_req_mgr_core_session *cam_session;
-	struct cam_req_mgr_core_link    *link1 = NULL;
-	struct cam_req_mgr_core_link    *link2 = NULL;
+	struct cam_req_mgr_core_link    *link[MAX_LINKS_PER_SESSION];
 
 	if (!sync_info) {
 		CAM_ERR(CAM_CRM, "NULL pointer");
@@ -3968,58 +3980,61 @@ int cam_req_mgr_sync_config(
 
 	mutex_lock(&cam_session->lock);
 
-	CAM_DBG(CAM_CRM, "link handles %x %x",
-		sync_info->link_hdls[0], sync_info->link_hdls[1]);
+	for (i = 0; i < sync_info->num_links; i++) {
 
-	/* only two links existing per session in dual cam use case*/
-	link1 = cam_get_device_priv(sync_info->link_hdls[0]);
-	if (!link1) {
-		CAM_ERR(CAM_CRM, "link1 NULL pointer");
-		rc = -EINVAL;
-		goto done;
-	}
-
-	link2 = cam_get_device_priv(sync_info->link_hdls[1]);
-	if (!link2) {
-		CAM_ERR(CAM_CRM, "link2 NULL pointer");
-		rc = -EINVAL;
-		goto done;
-	}
-
-	link1->sync_link_sof_skip = false;
-	link1->sync_link = NULL;
+		if (!sync_info->link_hdls[i]) {
+			CAM_ERR(CAM_CRM, "link handle %d is null", i);
+			rc = -EINVAL;
+			goto done;
+		}
 
-	link2->sync_link_sof_skip = false;
-	link2->sync_link = NULL;
+		link[i] = cam_get_device_priv(sync_info->link_hdls[i]);
+		if (!link[i]) {
+			CAM_ERR(CAM_CRM, "link%d NULL pointer", i);
+			rc = -EINVAL;
+			goto done;
+		}
 
-	link1->is_master = false;
-	link2->is_master = false;
+		link[i]->sync_link_sof_skip = false;
+		link[i]->is_master = false;
+		link[i]->in_msync_mode = false;
+		link[i]->initial_sync_req = -1;
 
-	link1->in_msync_mode = false;
-	link2->in_msync_mode = false;
-	link1->initial_sync_req = -1;
-	link2->initial_sync_req = -1;
+		for (j = 0; j < sync_info->num_links-1; j++)
+			link[i]->sync_link[j] = NULL;
+	}
 
 	if (sync_info->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC) {
-		link1->sync_link = link2;
-		link2->sync_link = link1;
-		__cam_req_mgr_set_master_link(link1, link2);
+		for (i = 0; i < sync_info->num_links; i++) {
+			j = 0;
+			sync_idx = 0;
+			CAM_DBG(CAM_REQ, "link %x adds sync link:",
+				link[i]->link_hdl);
+			while (j < sync_info->num_links) {
+				if (i != j) {
+					link[i]->sync_link[sync_idx++] =
+						link[j];
+					link[i]->num_sync_links++;
+					CAM_DBG(CAM_REQ, "sync_link[%d] : %x",
+						sync_idx-1, link[j]->link_hdl);
+				}
+				j++;
+			}
+			link[i]->initial_skip = true;
+			link[i]->sof_timestamp = 0;
+		}
 	} else {
-		/*
-		 * Reset below info after the mode is configured
-		 * to NO-SYNC mode since they may be overridden
-		 * if the sync config is invoked after SOF comes.
-		 */
-		link1->initial_skip = true;
-		link2->initial_skip = true;
-		link1->sof_timestamp = 0;
-		link2->sof_timestamp = 0;
+		for (j = 0; j < sync_info->num_links; j++) {
+			link[j]->initial_skip = true;
+			link[j]->sof_timestamp = 0;
+			link[j]->num_sync_links = 0;
+		}
 	}
 
 	cam_session->sync_mode = sync_info->sync_mode;
 	CAM_DBG(CAM_REQ,
-		"Sync config on link1 0x%x & link2 0x%x with sync_mode %d",
-		link1->link_hdl, link2->link_hdl, cam_session->sync_mode);
+		"Sync config completed on %d links with sync_mode %d",
+		sync_info->num_links, sync_info->sync_mode);
 
 done:
 	mutex_unlock(&cam_session->lock);

+ 5 - 2
drivers/cam_req_mgr/cam_req_mgr_core.h

@@ -343,7 +343,8 @@ struct cam_req_mgr_connected_device {
  * @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            : pointer to the sync link for synchronization
+ * @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
  *                         frame in a particular link skip corresponding
  *                         frame in sync link as well.
@@ -387,7 +388,9 @@ struct cam_req_mgr_core_link {
 	spinlock_t                           link_state_spin_lock;
 	uint32_t                             subscribe_event;
 	uint32_t                             trigger_mask;
-	struct cam_req_mgr_core_link        *sync_link;
+	struct cam_req_mgr_core_link
+			*sync_link[MAXIMUM_LINKS_PER_SESSION - 1];
+	int32_t                              num_sync_links;
 	bool                                 sync_link_sof_skip;
 	int32_t                              open_req_cnt;
 	uint32_t                             last_flush_id;