Explorar o código

msm: camera: isp: Notify CRM to pause SOF timer after flush

Adding CRM interface to stop SOF timer from isp during flush.
During flush hardware is getting stop and will not send SOF
notification to CRM so need to pause SOF timer. Whenever SOF
timer will get expire,do not need to send error to UMD during
pause time.

CRs-Fixed: 2564389
Change-Id: I6d85f2c658c30dbe211f0ec9d83bca323a5c265b
Signed-off-by: Chandan Kumar Jha <[email protected]>
Chandan Kumar Jha %!s(int64=5) %!d(string=hai) anos
pai
achega
fc8ddd752d

+ 9 - 0
drivers/cam_isp/cam_isp_context.c

@@ -2165,6 +2165,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
 	struct cam_hw_stop_args           stop_args;
 	struct cam_hw_reset_args          reset_args;
 	struct cam_hw_cmd_args            hw_cmd_args;
+	struct cam_req_mgr_timer_notify    timer;
 
 	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
 
@@ -2210,6 +2211,14 @@ static int __cam_isp_ctx_flush_req_in_top_state(
 
 		CAM_INFO(CAM_ISP, "Stop HW complete. Reset HW next.");
 		CAM_DBG(CAM_ISP, "Flush wait and active lists");
+
+		if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_timer) {
+			timer.link_hdl = ctx->link_hdl;
+			timer.dev_hdl = ctx->dev_hdl;
+			timer.state = false;
+			ctx->ctx_crm_intf->notify_timer(&timer);
+		}
+
 		spin_lock_bh(&ctx->lock);
 		if (!list_empty(&ctx->wait_req_list))
 			rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list,

+ 55 - 0
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -1744,6 +1744,10 @@ static void __cam_req_mgr_sof_freeze(struct timer_list *timer_data)
 	}
 
 	link = (struct cam_req_mgr_core_link *)timer->parent;
+
+	if (link->watchdog->pause_timer)
+		return;
+
 	task = cam_req_mgr_workq_get_task(link->workq);
 	if (!task) {
 		CAM_ERR(CAM_CRM, "No empty task");
@@ -2643,6 +2647,52 @@ end:
 	return rc;
 }
 
+/**
+ * cam_req_mgr_cb_notify_timer()
+ *
+ * @brief      : Notify SOF timer to pause after flush
+ * @timer_data : contains information about frame_id, link etc.
+ *
+ * @return  : 0 on success
+ *
+ */
+static int cam_req_mgr_cb_notify_timer(
+	struct cam_req_mgr_timer_notify *timer_data)
+{
+	int                              rc = 0;
+	struct cam_req_mgr_core_link    *link = NULL;
+
+	if (!timer_data) {
+		CAM_ERR(CAM_CRM, "timer data  is NULL");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	link = (struct cam_req_mgr_core_link *)
+		cam_get_device_priv(timer_data->link_hdl);
+	if (!link) {
+		CAM_DBG(CAM_CRM, "link ptr NULL %x", timer_data->link_hdl);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	spin_lock_bh(&link->link_state_spin_lock);
+	if (link->state < CAM_CRM_LINK_STATE_READY) {
+		CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
+		spin_unlock_bh(&link->link_state_spin_lock);
+		rc = -EPERM;
+		goto end;
+	}
+	spin_unlock_bh(&link->link_state_spin_lock);
+
+
+	if (!timer_data->state)
+		link->watchdog->pause_timer = true;
+
+end:
+	return rc;
+}
+
 /**
  * cam_req_mgr_cb_notify_trigger()
  *
@@ -2682,6 +2732,10 @@ static int cam_req_mgr_cb_notify_trigger(
 		rc = -EPERM;
 		goto end;
 	}
+
+	if (link->watchdog->pause_timer)
+		link->watchdog->pause_timer = false;
+
 	crm_timer_reset(link->watchdog);
 	spin_unlock_bh(&link->link_state_spin_lock);
 
@@ -2711,6 +2765,7 @@ static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
 	.notify_trigger = cam_req_mgr_cb_notify_trigger,
 	.notify_err     = cam_req_mgr_cb_notify_err,
 	.add_req        = cam_req_mgr_cb_add_req,
+	.notify_timer   = cam_req_mgr_cb_notify_timer,
 };
 
 /**

+ 16 - 0
drivers/cam_req_mgr/cam_req_mgr_interface.h

@@ -14,6 +14,7 @@
 struct cam_req_mgr_trigger_notify;
 struct cam_req_mgr_error_notify;
 struct cam_req_mgr_add_request;
+struct cam_req_mgr_timer_notify;
 struct cam_req_mgr_device_info;
 struct cam_req_mgr_core_dev_link_setup;
 struct cam_req_mgr_apply_request;
@@ -35,6 +36,7 @@ typedef int (*cam_req_mgr_notify_trigger)(
 	struct cam_req_mgr_trigger_notify *);
 typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *);
 typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *);
+typedef int (*cam_req_mgr_notify_timer)(struct cam_req_mgr_timer_notify *);
 
 /**
  * @brief: cam req mgr to camera device drivers
@@ -64,6 +66,7 @@ struct cam_req_mgr_crm_cb {
 	cam_req_mgr_notify_trigger  notify_trigger;
 	cam_req_mgr_notify_err      notify_err;
 	cam_req_mgr_add_req         add_req;
+	cam_req_mgr_notify_timer    notify_timer;
 };
 
 /**
@@ -206,6 +209,19 @@ struct cam_req_mgr_trigger_notify {
 	uint64_t sof_timestamp_val;
 };
 
+/**
+ * struct cam_req_mgr_timer_notify
+ * @link_hdl : link identifier
+ * @dev_hdl  : device handle which has sent this req id
+ * @frame_id : frame id for internal tracking
+ * @state    : timer state i.e ON or OFF
+ */
+struct cam_req_mgr_timer_notify {
+	int32_t  link_hdl;
+	int32_t  dev_hdl;
+	bool     state;
+};
+
 /**
  * struct cam_req_mgr_error_notify
  * @link_hdl : link identifier

+ 7 - 5
drivers/cam_req_mgr/cam_req_mgr_timer.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_REQ_MGR_TIMER_H_
@@ -12,16 +12,18 @@
 #include "cam_req_mgr_core_defs.h"
 
 /** struct cam_req_mgr_timer
- * @expires   : timeout value for timer
- * @sys_timer : system timer variable
- * @parent    : priv data - link pointer
- * @timer_cb  : callback func which will be called when timeout expires
+ * @expires      : timeout value for timer
+ * @sys_timer    : system timer variable
+ * @parent       : priv data - link pointer
+ * @timer_cb     : callback func which will be called when timeout expires
+ * @pause_timer  : flag to pause SOF timer
  */
 struct cam_req_mgr_timer {
 	int32_t            expires;
 	struct timer_list  sys_timer;
 	void               *parent;
 	void               (*timer_cb)(struct timer_list *timer_data);
+	bool                pause_timer;
 };
 
 /**