فهرست منبع

msm: camera: core: validation of session/device/link handle

This change is to validate session, device and link handle.
Also, checks whether the device handle belongs to
correct session handle or not.

CRs-Fixed: 3496553
Change-Id: I6b86bf7d0908a280e90e085a3b3e1727facdf8c6
Signed-off-by: Karthik Dillibabu <[email protected]>
Karthik Dillibabu 2 سال پیش
والد
کامیت
f1adead069

+ 31 - 52
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -841,8 +841,7 @@ static void __cam_req_mgr_disconnect_req_on_sync_link(
 	struct cam_req_mgr_core_link *sync_link;
 
 	for (i = 0; i < slot->num_sync_links; i++) {
-		sync_link = (struct cam_req_mgr_core_link *)
-			cam_get_device_priv(slot->sync_link_hdls[i]);
+		sync_link = cam_get_link_priv(slot->sync_link_hdls[i]);
 		if (!sync_link)
 			continue;
 
@@ -2238,8 +2237,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
 			} else {
 				num_sync_links = slot->num_sync_links;
 				for (i = 0; i < num_sync_links; i++)
-					sync_link[i] = (struct cam_req_mgr_core_link *)
-						cam_get_device_priv(slot->sync_link_hdls[i]);
+					sync_link[i] = cam_get_link_priv(slot->sync_link_hdls[i]);
 			}
 			rc = __cam_req_mgr_check_multi_sync_link_ready(
 				link, sync_link, slot, num_sync_links, trigger);
@@ -3892,9 +3890,7 @@ static int cam_req_mgr_cb_add_req(struct cam_req_mgr_add_request *add_req)
 		return -EINVAL;
 	}
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(add_req->link_hdl);
-
+	link = cam_get_link_priv(add_req->link_hdl);
 	if (!link) {
 		CAM_DBG(CAM_CRM, "link ptr NULL %x", add_req->link_hdl);
 		return -EINVAL;
@@ -3991,8 +3987,7 @@ static int cam_req_mgr_cb_notify_err(
 		goto end;
 	}
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(err_info->link_hdl);
+	link = cam_get_link_priv(err_info->link_hdl);
 	if (!link) {
 		CAM_DBG(CAM_CRM, "link ptr NULL %x", err_info->link_hdl);
 		rc = -EINVAL;
@@ -4095,8 +4090,7 @@ static int cam_req_mgr_cb_notify_timer(
 		goto end;
 	}
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(timer_data->link_hdl);
+	link = cam_get_link_priv(timer_data->link_hdl);
 	if (!link) {
 		CAM_DBG(CAM_CRM, "link ptr NULL %x", timer_data->link_hdl);
 		rc = -EINVAL;
@@ -4150,8 +4144,7 @@ static int cam_req_mgr_cb_notify_stop(
 		goto end;
 	}
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(stop_info->link_hdl);
+	link = cam_get_link_priv(stop_info->link_hdl);
 	if (!link) {
 		CAM_DBG(CAM_CRM, "link ptr NULL %x", stop_info->link_hdl);
 		rc = -EINVAL;
@@ -4216,8 +4209,7 @@ static int cam_req_mgr_cb_notify_trigger(
 		goto end;
 	}
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(trigger_data->link_hdl);
+	link = cam_get_link_priv(trigger_data->link_hdl);
 	if (!link) {
 		CAM_DBG(CAM_CRM, "link ptr NULL %x", trigger_data->link_hdl);
 		rc = -EINVAL;
@@ -4629,7 +4621,7 @@ static int __cam_req_mgr_unlink(
 	__cam_req_mgr_destroy_subdev(&link->l_dev);
 
 	/* Destroy the link handle */
-	rc = cam_destroy_device_hdl(link->link_hdl);
+	rc = cam_destroy_link_hdl(link->link_hdl);
 	if (rc < 0) {
 		CAM_ERR(CAM_CRM, "error destroying link hdl %x rc %d",
 			link->link_hdl, rc);
@@ -4655,8 +4647,7 @@ int cam_req_mgr_destroy_session(
 	}
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
-	cam_session = (struct cam_req_mgr_core_session *)
-		cam_get_device_priv(ses_info->session_hdl);
+	cam_session = cam_get_session_priv(ses_info->session_hdl);
 	if (!cam_session || (cam_session->session_hdl != ses_info->session_hdl)) {
 		CAM_ERR(CAM_CRM, "session: %s, ses_info->ses_hdl:%x, session->ses_hdl:%x",
 			CAM_IS_NULL_TO_STR(cam_session), ses_info->session_hdl,
@@ -4728,8 +4719,7 @@ int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info)
 	mutex_lock(&g_crm_core_dev->crm_lock);
 
 	/* session hdl's priv data is cam session struct */
-	cam_session = (struct cam_req_mgr_core_session *)
-		cam_get_device_priv(link_info->u.link_info_v1.session_hdl);
+	cam_session = cam_get_session_priv(link_info->u.link_info_v1.session_hdl);
 	if (!cam_session || (cam_session->session_hdl != link_info->u.link_info_v1.session_hdl)) {
 		CAM_ERR(CAM_CRM, "session: %s, link_info->ses_hdl:%x, session->ses_hdl:%x",
 			CAM_IS_NULL_TO_STR(cam_session), link_info->u.link_info_v1.session_hdl,
@@ -4752,8 +4742,8 @@ int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info)
 	root_dev.dev_id = CAM_CRM;
 
 	mutex_lock(&link->lock);
-	/* Create unique dev handle for link */
-	link->link_hdl = cam_create_device_hdl(&root_dev);
+	/* Create unique handle for link */
+	link->link_hdl = cam_create_link_hdl(&root_dev);
 	if (link->link_hdl < 0) {
 		CAM_ERR(CAM_CRM,
 			"Insufficient memory to create new device handle");
@@ -4808,7 +4798,7 @@ int cam_req_mgr_link(struct cam_req_mgr_ver_info *link_info)
 setup_failed:
 	__cam_req_mgr_destroy_subdev(&link->l_dev);
 create_subdev_failed:
-	cam_destroy_device_hdl(link->link_hdl);
+	cam_destroy_link_hdl(link->link_hdl);
 	link_info->u.link_info_v1.link_hdl = -1;
 link_hdl_fail:
 	mutex_unlock(&link->lock);
@@ -4840,8 +4830,7 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info)
 	mutex_lock(&g_crm_core_dev->crm_lock);
 
 	/* session hdl's priv data is cam session struct */
-	cam_session = (struct cam_req_mgr_core_session *)
-		cam_get_device_priv(link_info->u.link_info_v2.session_hdl);
+	cam_session = cam_get_session_priv(link_info->u.link_info_v2.session_hdl);
 	if (!cam_session || (cam_session->session_hdl != link_info->u.link_info_v2.session_hdl)) {
 		CAM_ERR(CAM_CRM, "session: %s, link_info->ses_hdl:%x, session->ses_hdl:%x",
 			CAM_IS_NULL_TO_STR(cam_session), link_info->u.link_info_v2.session_hdl,
@@ -4864,8 +4853,8 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info)
 	root_dev.dev_id = CAM_CRM;
 
 	mutex_lock(&link->lock);
-	/* Create unique dev handle for link */
-	link->link_hdl = cam_create_device_hdl(&root_dev);
+	/* Create unique handle for link */
+	link->link_hdl = cam_create_link_hdl(&root_dev);
 	if (link->link_hdl < 0) {
 		CAM_ERR(CAM_CRM,
 			"Insufficient memory to create new device handle");
@@ -4925,7 +4914,7 @@ int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info)
 setup_failed:
 	__cam_req_mgr_destroy_subdev(&link->l_dev);
 create_subdev_failed:
-	cam_destroy_device_hdl(link->link_hdl);
+	cam_destroy_link_hdl(link->link_hdl);
 	link_info->u.link_info_v2.link_hdl = -1;
 link_hdl_fail:
 	mutex_unlock(&link->lock);
@@ -4950,8 +4939,7 @@ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info)
 	CAM_DBG(CAM_CRM, "link_hdl %x", unlink_info->link_hdl);
 
 	/* session hdl's priv data is cam session struct */
-	cam_session = (struct cam_req_mgr_core_session *)
-		cam_get_device_priv(unlink_info->session_hdl);
+	cam_session = cam_get_session_priv(unlink_info->session_hdl);
 	if (!cam_session || (cam_session->session_hdl != unlink_info->session_hdl)) {
 		CAM_ERR(CAM_CRM, "session: %s, unlink_info->ses_hdl:%x, cam_session->ses_hdl:%x",
 			CAM_IS_NULL_TO_STR(cam_session), unlink_info->session_hdl,
@@ -4961,7 +4949,7 @@ int cam_req_mgr_unlink(struct cam_req_mgr_unlink_info *unlink_info)
 	}
 
 	/* link hdl's priv data is core_link struct */
-	link = cam_get_device_priv(unlink_info->link_hdl);
+	link = cam_get_link_priv(unlink_info->link_hdl);
 	if (!link || (link->link_hdl != unlink_info->link_hdl)) {
 		CAM_ERR(CAM_CRM, "link: %s, unlink_info->link_hdl:%x, link->link_hdl:%x",
 			CAM_IS_NULL_TO_STR(link), unlink_info->link_hdl,
@@ -4996,8 +4984,7 @@ int cam_req_mgr_schedule_request(
 	}
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(sched_req->link_hdl);
+	link = cam_get_link_priv(sched_req->link_hdl);
 	if (!link || (link->link_hdl != sched_req->link_hdl)) {
 		CAM_ERR(CAM_CRM, "link: %s, sched_req->link_hdl:%x, link->link_hdl:%x",
 			CAM_IS_NULL_TO_STR(link), sched_req->link_hdl,
@@ -5062,8 +5049,7 @@ int cam_req_mgr_schedule_request_v2(
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(sched_req->link_hdl);
+	link = cam_get_link_priv(sched_req->link_hdl);
 	if (!link || (link->link_hdl != sched_req->link_hdl)) {
 		CAM_ERR(CAM_CRM, "link: %s, sched_req->link_hdl:%x, link->link_hdl:%x",
 			CAM_IS_NULL_TO_STR(link), sched_req->link_hdl,
@@ -5124,8 +5110,7 @@ int cam_req_mgr_schedule_request_v2(
 				goto end;
 			}
 
-			sync_links[i] = (struct cam_req_mgr_core_link *)
-				cam_get_device_priv(sched_req->link_hdls[i]);
+			sync_links[i] = cam_get_link_priv(sched_req->link_hdls[i]);
 			if (!sync_links[i] ||
 				(sync_links[i]->link_hdl != sched_req->link_hdls[i])) {
 				CAM_ERR(CAM_CRM,
@@ -5187,8 +5172,7 @@ int cam_req_mgr_sync_config(
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
 	/* session hdl's priv data is cam session struct */
-	cam_session = (struct cam_req_mgr_core_session *)
-		cam_get_device_priv(sync_info->session_hdl);
+	cam_session = cam_get_session_priv(sync_info->session_hdl);
 	if (!cam_session || (cam_session->session_hdl != sync_info->session_hdl)) {
 		CAM_ERR(CAM_CRM, "session: %s, sync_info->session_hdl:%x, session->ses_hdl:%x",
 			CAM_IS_NULL_TO_STR(cam_session), sync_info->session_hdl,
@@ -5207,7 +5191,7 @@ int cam_req_mgr_sync_config(
 			goto done;
 		}
 
-		link[i] = cam_get_device_priv(sync_info->link_hdls[i]);
+		link[i] = cam_get_link_priv(sync_info->link_hdls[i]);
 		if (!link[i] || (link[i]->link_hdl != sync_info->link_hdls[i])) {
 			CAM_ERR(CAM_CRM, "link: %s, sync_info->link_hdl:%x, link->link_hdl:%x",
 				CAM_IS_NULL_TO_STR(link), sync_info->link_hdls[i],
@@ -5284,9 +5268,9 @@ int cam_req_mgr_flush_requests(
 	}
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
+
 	/* session hdl's priv data is cam session struct */
-	session = (struct cam_req_mgr_core_session *)
-		cam_get_device_priv(flush_info->session_hdl);
+	session = cam_get_session_priv(flush_info->session_hdl);
 	if (!session || (session->session_hdl != flush_info->session_hdl)) {
 		CAM_ERR(CAM_CRM, "session: %s, flush_info->ses_hdl:%x, session->ses_hdl:%x",
 			CAM_IS_NULL_TO_STR(session), flush_info->session_hdl,
@@ -5300,8 +5284,7 @@ int cam_req_mgr_flush_requests(
 		goto end;
 	}
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(flush_info->link_hdl);
+	link = cam_get_link_priv(flush_info->link_hdl);
 	if (!link || (link->link_hdl != flush_info->link_hdl)) {
 		CAM_ERR(CAM_CRM, "link: %s, flush_info->link_hdl:%x, link->link_hdl:%x",
 			CAM_IS_NULL_TO_STR(link), flush_info->link_hdl,
@@ -5365,8 +5348,7 @@ int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
 	for (i = 0; i < control->num_links; i++) {
-		link = (struct cam_req_mgr_core_link *)
-			cam_get_device_priv(control->link_hdls[i]);
+		link = cam_get_link_priv(control->link_hdls[i]);
 		if (!link || (link->link_hdl != control->link_hdls[i])) {
 			CAM_ERR(CAM_CRM, "link: %s, control->link_hdl:%x, link->link_hdl:%x",
 				CAM_IS_NULL_TO_STR(link), control->link_hdls[i],
@@ -5437,8 +5419,7 @@ int cam_req_mgr_link_properties(struct cam_req_mgr_link_properties *properties)
 	struct cam_req_mgr_link_evt_data       evt_data;
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(properties->link_hdl);
+	link = cam_get_link_priv(properties->link_hdl);
 	if (!link || (link->link_hdl != properties->link_hdl)) {
 		CAM_ERR(CAM_CRM, "link: %s, properties->link_hdl:0x%x, link->link_hdl:0x%x",
 			CAM_IS_NULL_TO_STR(link), properties->link_hdl,
@@ -5613,8 +5594,7 @@ int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req)
 
 	mutex_lock(&g_crm_core_dev->crm_lock);
 	/* session hdl's priv data is cam session struct */
-	session = (struct cam_req_mgr_core_session *)
-	    cam_get_device_priv(dump_req->session_handle);
+	session = cam_get_session_priv(dump_req->session_handle);
 	if (!session || (session->session_hdl != dump_req->session_handle)) {
 		CAM_ERR(CAM_CRM, "session: %s, dump_req->ses_hdl:%x, session->ses_hdl:%x",
 			CAM_IS_NULL_TO_STR(session), dump_req->session_handle,
@@ -5628,8 +5608,7 @@ int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req)
 		goto end;
 	}
 
-	link = (struct cam_req_mgr_core_link *)
-		cam_get_device_priv(dump_req->link_hdl);
+	link = cam_get_link_priv(dump_req->link_hdl);
 	if (!link || (link->link_hdl != dump_req->link_hdl)) {
 		CAM_ERR(CAM_CRM, "link: %s, dump_req->link_hdl:%x, link->link_hdl:%x",
 			CAM_IS_NULL_TO_STR(link), dump_req->link_hdl,

+ 99 - 15
drivers/cam_req_mgr/cam_req_mgr_util.c

@@ -37,28 +37,29 @@ int cam_req_mgr_util_init(void)
 		rc = -ENOMEM;
 		goto hdl_tbl_alloc_failed;
 	}
+	bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES_V2) * sizeof(long);
+	hdl_tbl_local->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!hdl_tbl_local->bitmap) {
+		rc = -ENOMEM;
+		goto bitmap_alloc_fail;
+	}
+	hdl_tbl_local->bits = bitmap_size * BITS_PER_BYTE;
+
 	spin_lock_bh(&hdl_tbl_lock);
 	if (hdl_tbl) {
 		spin_unlock_bh(&hdl_tbl_lock);
 		rc = -EEXIST;
+		kfree(hdl_tbl_local->bitmap);
 		kfree(hdl_tbl_local);
 		goto hdl_tbl_check_failed;
 	}
 	hdl_tbl = hdl_tbl_local;
 	spin_unlock_bh(&hdl_tbl_lock);
 
-	bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES_V2) * sizeof(long);
-	hdl_tbl->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!hdl_tbl->bitmap) {
-		rc = -ENOMEM;
-		goto bitmap_alloc_fail;
-	}
-	hdl_tbl->bits = bitmap_size * BITS_PER_BYTE;
-
 	return rc;
 
 bitmap_alloc_fail:
-	kfree(hdl_tbl);
+	kfree(hdl_tbl_local);
 	hdl_tbl = NULL;
 hdl_tbl_alloc_failed:
 hdl_tbl_check_failed:
@@ -163,6 +164,18 @@ static int32_t cam_get_free_handle_index(void)
 	return idx;
 }
 
+static void cam_dump_tbl_info(void)
+{
+	int i;
+
+	for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++)
+		CAM_INFO_RATE_LIMIT_CUSTOM(CAM_CRM, CAM_RATE_LIMIT_INTERVAL_5SEC,
+			CAM_REQ_MGR_MAX_HANDLES_V2,
+			"session_hdl=%x hdl_value=%x type=%d state=%d dev_id=%lld",
+			hdl_tbl->hdl[i].session_hdl, hdl_tbl->hdl[i].hdl_value,
+			hdl_tbl->hdl[i].type, hdl_tbl->hdl[i].state, hdl_tbl->hdl[i].dev_id);
+}
+
 int32_t cam_create_session_hdl(void *priv)
 {
 	int idx;
@@ -178,7 +191,8 @@ int32_t cam_create_session_hdl(void *priv)
 
 	idx = cam_get_free_handle_index();
 	if (idx < 0) {
-		CAM_ERR(CAM_CRM, "Unable to create session handle");
+		CAM_ERR(CAM_CRM, "Unable to create session handle(idx = %d)", idx);
+		cam_dump_tbl_info();
 		spin_unlock_bh(&hdl_tbl_lock);
 		return idx;
 	}
@@ -219,8 +233,8 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
 
 	idx = cam_get_free_handle_index();
 	if (idx < 0) {
-		CAM_ERR(CAM_CRM,
-			"Unable to create device handle(idx= %d)", idx);
+		CAM_ERR(CAM_CRM, "Unable to create device handle(idx= %d)", idx);
+		cam_dump_tbl_info();
 		spin_unlock_bh(&hdl_tbl_lock);
 		return idx;
 	}
@@ -240,7 +254,43 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
 	return handle;
 }
 
-void *cam_get_device_priv(int32_t dev_hdl)
+int32_t cam_create_link_hdl(struct cam_create_dev_hdl *hdl_data)
+{
+	int idx;
+	int rand = 0;
+	int32_t handle;
+
+	spin_lock_bh(&hdl_tbl_lock);
+	if (!hdl_tbl) {
+		CAM_ERR(CAM_CRM, "Hdl tbl is NULL");
+		spin_unlock_bh(&hdl_tbl_lock);
+		return -EINVAL;
+	}
+
+	idx = cam_get_free_handle_index();
+	if (idx < 0) {
+		CAM_ERR(CAM_CRM, "Unable to create link handle(idx = %d)", idx);
+		cam_dump_tbl_info();
+		spin_unlock_bh(&hdl_tbl_lock);
+		return idx;
+	}
+
+	get_random_bytes(&rand, CAM_REQ_MGR_RND1_BYTES);
+	handle = GET_DEV_HANDLE(rand, HDL_TYPE_LINK, idx);
+	hdl_tbl->hdl[idx].session_hdl = hdl_data->session_hdl;
+	hdl_tbl->hdl[idx].hdl_value = handle;
+	hdl_tbl->hdl[idx].type = HDL_TYPE_LINK;
+	hdl_tbl->hdl[idx].state = HDL_ACTIVE;
+	hdl_tbl->hdl[idx].priv = hdl_data->priv;
+	hdl_tbl->hdl[idx].ops = NULL;
+	hdl_tbl->hdl[idx].dev_id = hdl_data->dev_id;
+	spin_unlock_bh(&hdl_tbl_lock);
+
+	CAM_DBG(CAM_CRM, "handle = %x", handle);
+	return handle;
+}
+
+void *cam_get_priv(int32_t dev_hdl, int handle_type)
 {
 	int idx;
 	int type;
@@ -271,7 +321,7 @@ void *cam_get_device_priv(int32_t dev_hdl)
 	}
 
 	type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
-	if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) {
+	if (type != handle_type) {
 		CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid type:%d", type);
 		goto device_priv_fail;
 	}
@@ -286,6 +336,34 @@ device_priv_fail:
 	return NULL;
 }
 
+void *cam_get_device_priv(int32_t dev_hdl)
+{
+	void *priv;
+
+	priv = cam_get_priv(dev_hdl, HDL_TYPE_DEV);
+	return priv;
+}
+
+struct cam_req_mgr_core_session *cam_get_session_priv(int32_t dev_hdl)
+{
+	struct cam_req_mgr_core_session *priv;
+
+	priv = (struct cam_req_mgr_core_session *)
+		cam_get_priv(dev_hdl, HDL_TYPE_SESSION);
+
+	return priv;
+}
+
+struct cam_req_mgr_core_link *cam_get_link_priv(int32_t dev_hdl)
+{
+	struct cam_req_mgr_core_link *priv;
+
+	priv = (struct cam_req_mgr_core_link *)
+		cam_get_priv(dev_hdl, HDL_TYPE_LINK);
+
+	return priv;
+}
+
 void *cam_get_device_ops(int32_t dev_hdl)
 {
 	int idx;
@@ -310,7 +388,7 @@ void *cam_get_device_ops(int32_t dev_hdl)
 	}
 
 	type = CAM_REQ_MGR_GET_HDL_TYPE(dev_hdl);
-	if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type) {
+	if (HDL_TYPE_DEV != type && HDL_TYPE_SESSION != type && HDL_TYPE_LINK != type) {
 		CAM_ERR(CAM_CRM, "Invalid type");
 		goto device_ops_fail;
 	}
@@ -381,6 +459,12 @@ int cam_destroy_device_hdl(int32_t dev_hdl)
 	return cam_destroy_hdl(dev_hdl, HDL_TYPE_DEV);
 }
 
+int cam_destroy_link_hdl(int32_t dev_hdl)
+{
+	CAM_DBG(CAM_CRM, "handle = %x", dev_hdl);
+	return cam_destroy_hdl(dev_hdl, HDL_TYPE_LINK);
+}
+
 int cam_destroy_session_hdl(int32_t dev_hdl)
 {
 	return cam_destroy_hdl(dev_hdl, HDL_TYPE_SESSION);

+ 46 - 5
drivers/cam_req_mgr/cam_req_mgr_util.h

@@ -22,12 +22,14 @@ enum hdl_state {
 
 /**
  * handle type
- * @HDL_TYPE_DEV: for device and link
+ * @HDL_TYPE_DEV: for device
  * @HDL_TYPE_SESSION: for session
+ * @HDL_TYPE_LINK: for link
  */
 enum hdl_type {
 	HDL_TYPE_DEV = 1,
-	HDL_TYPE_SESSION
+	HDL_TYPE_SESSION,
+	HDL_TYPE_LINK
 };
 
 /**
@@ -115,8 +117,19 @@ int32_t cam_create_session_hdl(void *priv);
 int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data);
 
 /**
- * cam_get_device_priv() - get private data of a handle
- * @dev_hdl: handle for a session/link/device
+ * cam_create_link_hdl() - create a link handle
+ * @hdl_data: session hdl, flags, ops and priv dara as input
+ *
+ * cam_req_mgr_core calls this function to get
+ * session and link handles
+ * KMD drivers calls this function to create
+ * a link handle. Returns a unique link handle
+ */
+int32_t cam_create_link_hdl(struct cam_create_dev_hdl *hdl_data);
+
+/**
+ * cam_get_device_priv() - get private data of a device handle
+ * @dev_hdl: handle for a device
  *
  * cam_req_mgr_core and KMD drivers use this function to
  * get private data of a handle. Returns a private data
@@ -124,6 +137,26 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data);
  */
 void *cam_get_device_priv(int32_t dev_hdl);
 
+/**
+ * cam_get_session_priv() - get private data of a session handle
+ * @dev_hdl: handle for a session
+ *
+ * cam_req_mgr_core and KMD drivers use this function to
+ * get private data of a handle. Returns a private data
+ * structure pointer.
+ */
+struct cam_req_mgr_core_session *cam_get_session_priv(int32_t dev_hdl);
+
+/**
+ * cam_get_link_priv() - get private data of a link handle
+ * @dev_hdl: handle for a link
+ *
+ * cam_req_mgr_core and KMD drivers use this function to
+ * get private data of a handle. Returns a private data
+ * structure pointer.
+ */
+struct cam_req_mgr_core_link *cam_get_link_priv(int32_t dev_hdl);
+
 /**
  * cam_get_device_ops() - get ops of a handle
  * @dev_hdl: handle for a session/link/device
@@ -135,12 +168,20 @@ void *cam_get_device_ops(int32_t dev_hdl);
 
 /**
  * cam_destroy_device_hdl() - destroy device handle
- * @dev_hdl: handle for a link/device.
+ * @dev_hdl: handle for a device.
  *
  * Returns success/failure
  */
 int32_t cam_destroy_device_hdl(int32_t dev_hdl);
 
+/**
+ * cam_destroy_link_hdl() - destroy link handle
+ * @dev_hdl: handle for a link.
+ *
+ * Returns success/failure
+ */
+int32_t cam_destroy_link_hdl(int32_t dev_hdl);
+
 /**
  * cam_destroy_session_hdl() - destroy device handle
  * @dev_hdl: handle for a session

+ 3 - 0
include/uapi/camera/media/cam_req_mgr.h

@@ -50,6 +50,9 @@
 #define CAM_REQ_MGR_MAX_HANDLES_V2        256
 #define MAX_LINKS_PER_SESSION             2
 
+/* Interval for cam_info_rate_limit_custom() */
+#define CAM_RATE_LIMIT_INTERVAL_5SEC 5
+
 /* V4L event type which user space will subscribe to */
 #define V4L_EVENT_CAM_REQ_MGR_EVENT       (V4L2_EVENT_PRIVATE_START + 0)