Browse Source

msm: camera: common: Enhance error injection framework

Update from error injection framework to event injection framework to
support PF event inducement and node event. Different set of user
input parameters are required dependent on which event to injection.

ICP and ISP support error event and page fault event injection. JPEG
supports node event and page fault event injection. However, buf done
error injection is only supported for JPEG and ICP.

Create a query API to check whether PF is fatal for a context bank.
Using the API, if PF is fatal, page fault event injection is not
supported for the device that owns the context bank.

Make change to JPEG context event callback handling to account for
various events including Event Injection event.

CRs-Fixed: 3210139
Change-Id: I582ee0bda8dbf631ece2522a5a8145f38ec71928
Signed-off-by: Sokchetra Eung <[email protected]>
Sokchetra Eung 3 years ago
parent
commit
c87d8891b9

+ 5 - 5
drivers/cam_core/cam_context.c

@@ -788,7 +788,7 @@ void cam_context_getref(struct cam_context *ctx)
 		ctx->dev_name);
 }
 
-int cam_context_add_err_inject(struct cam_context *ctx, void *err_param)
+int cam_context_add_evt_inject(struct cam_context *ctx, void *evt_args)
 {
 	int rc = 0;
 
@@ -800,11 +800,11 @@ int cam_context_add_err_inject(struct cam_context *ctx, void *err_param)
 	mutex_lock(&ctx->ctx_mutex);
 	if ((ctx->state > CAM_CTX_AVAILABLE) &&
 		(ctx->state < CAM_CTX_STATE_MAX)) {
-		if (ctx->state_machine[ctx->state].err_inject_ops) {
-			rc = ctx->state_machine[ctx->state].err_inject_ops(
-				ctx, err_param);
+		if (ctx->state_machine[ctx->state].evt_inject_ops) {
+			rc = ctx->state_machine[ctx->state].evt_inject_ops(
+				ctx, evt_args);
 		} else {
-			CAM_WARN(CAM_CORE, "No err inject ops in dev %d,state %d",
+			CAM_WARN(CAM_CORE, "No evt inject ops in dev %d, state %d",
 				ctx->dev_hdl, ctx->state);
 		}
 	} else {

+ 8 - 8
drivers/cam_core/cam_context.h

@@ -165,7 +165,7 @@ struct cam_ctx_crm_ops {
  *                         context info
  * @recovery_ops:          Function to be invoked to try hardware recovery
  * @mini_dump_ops:         Function for mini dump
- * @err_inject_ops:        Function for error injection
+ * @evt_inject_ops:        Function for event injection
  *
  */
 struct cam_ctx_ops {
@@ -176,7 +176,7 @@ struct cam_ctx_ops {
 	cam_ctx_info_dump_cb_func    dumpinfo_ops;
 	cam_ctx_recovery_cb_func     recovery_ops;
 	cam_ctx_mini_dump_cb_func    mini_dump_ops;
-	cam_ctx_err_inject_cb_func   err_inject_ops;
+	cam_ctx_err_inject_cb_func   evt_inject_ops;
 };
 
 
@@ -601,16 +601,16 @@ void cam_context_putref(struct cam_context *ctx);
 void cam_context_getref(struct cam_context *ctx);
 
 /**
- * cam_context_add_err_inject()
+ * cam_context_add_evt_inject()
  *
- * @brief:     Add error inject parameters through err_inject_ops.
+ * @brief:       Add error inject parameters through evt_inject_ops.
  *
- * @ctx:       Context for which error is to be injected
+ * @ctx:         Context for which error is to be injected
  *
- * @err_param: Error injection parameters
+ * @inject_args: Event injection parameters
  *
  */
-int cam_context_add_err_inject(struct cam_context *ctx,
-	void *err_param);
+int cam_context_add_evt_inject(struct cam_context *ctx,
+	void *inject_args);
 
 #endif  /* _CAM_CONTEXT_H_ */

+ 116 - 11
drivers/cam_core/cam_context_utils.c

@@ -1744,21 +1744,126 @@ end:
 	*bytes_updated = bytes_written;
 }
 
-int cam_context_err_to_hw(struct cam_context *ctx, void *args)
+static int cam_context_apply_buf_done_err_injection(struct cam_context *ctx,
+	struct cam_common_evt_inject_data *inject_evt)
 {
-	int rc = -EINVAL;
+	struct cam_hw_done_event_data *buf_done_data = inject_evt->buf_done_data;
+	int rc;
 
-	if (!ctx || !args) {
-		CAM_ERR(CAM_CTXT, "invalid params for error injection");
-		return rc;
+	buf_done_data->evt_param = inject_evt->evt_params->u.buf_err_evt.sync_error;
+	rc = cam_context_buf_done_from_hw(ctx, buf_done_data,
+		CAM_CTX_EVT_ID_ERROR);
+	if (rc)
+		CAM_ERR(CAM_CTXT,
+			"Fail to apply buf done error injection with req id: %llu ctx id: %u rc: %d",
+			buf_done_data->request_id, ctx->ctx_id, rc);
+
+	return rc;
+}
+
+static int cam_context_apply_pf_evt_injection(struct cam_context *ctx,
+	struct cam_hw_inject_evt_param *evt_params)
+{
+	struct cam_hw_dump_pf_args pf_args         = {0};
+	struct cam_smmu_pf_info pf_info            = {0};
+	int rc;
+
+	pf_args.pf_context_info.req_id = evt_params->req_id;
+	pf_args.pf_context_info.ctx_found = evt_params->u.evt_notify.u.pf_evt_params.ctx_found;
+	pf_args.pf_smmu_info = &pf_info;
+
+	rc = cam_context_send_pf_evt(ctx, &pf_args);
+	if (rc)
+		CAM_ERR(CAM_CTXT,
+			"Fail to apply Page Fault event injection with req id: %llu ctx id: %u rc: %d",
+			evt_params->req_id, ctx->ctx_id, rc);
+
+	return rc;
+}
+
+static int cam_context_apply_node_event_injection(struct cam_context *ctx,
+	struct cam_hw_inject_evt_param *evt_params)
+{
+	struct cam_hw_inject_node_evt_param *node_evt_params =
+		&evt_params->u.evt_notify.u.node_evt_params;
+	struct cam_req_mgr_message req_msg                   = {0};
+	int rc;
+
+	req_msg.u.node_msg.request_id  = evt_params->req_id;
+	req_msg.u.node_msg.link_hdl    = ctx->link_hdl;
+	req_msg.u.node_msg.device_hdl  = ctx->dev_hdl;
+	req_msg.u.node_msg.event_type  = node_evt_params->event_type;
+	req_msg.u.node_msg.event_cause = node_evt_params->event_cause;
+	req_msg.session_hdl            = ctx->session_hdl;
+
+	rc = cam_req_mgr_notify_message(&req_msg,
+		V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT);
+	if (rc)
+		CAM_ERR(CAM_CTXT,
+			"Fail to apply error event injection with req id: %llu ctx id: %u rc: %d",
+			evt_params->req_id, ctx->ctx_id, rc);
+
+	return rc;
+}
+
+static int cam_context_apply_error_event_injection(struct cam_context *ctx,
+	struct cam_hw_inject_evt_param *evt_params)
+{
+	struct cam_hw_inject_err_evt_param *err_evt_params =
+		&evt_params->u.evt_notify.u.err_evt_params;
+	struct cam_req_mgr_message req_msg                 = {0};
+	int rc;
+
+	req_msg.u.err_msg.device_hdl    = ctx->dev_hdl;
+	req_msg.u.err_msg.error_type    = err_evt_params->err_type;
+	req_msg.u.err_msg.link_hdl      = ctx->link_hdl;
+	req_msg.u.err_msg.request_id    = evt_params->req_id;
+	req_msg.u.err_msg.resource_size = 0x0;
+	req_msg.u.err_msg.error_code    = err_evt_params->err_code;
+	req_msg.session_hdl             = ctx->session_hdl;
+
+	rc = cam_req_mgr_notify_message(&req_msg,
+		V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT);
+	if (rc)
+		CAM_ERR(CAM_CTXT,
+			"Fail to apply V4L2 Node event injection with req id: %llu ctx id: %u rc: %d",
+			evt_params->req_id, ctx->ctx_id, rc);
+
+	return rc;
+}
+
+int cam_context_apply_evt_injection(struct cam_context *ctx, void *inject_evt_arg)
+{
+	struct cam_common_evt_inject_data *inject_evt;
+	struct cam_hw_inject_evt_param *evt_params;
+	uint32_t evt_notify_type;
+	int rc = 0;
+
+	if (!ctx || !inject_evt_arg) {
+		CAM_ERR(CAM_CTXT, "Invalid parameters ctx %s inject evt args %s",
+			CAM_IS_NULL_TO_STR(ctx), CAM_IS_NULL_TO_STR(inject_evt_arg));
+		return -EINVAL;
 	}
 
-	if (ctx->hw_mgr_intf->hw_inject_err) {
-		ctx->hw_mgr_intf->hw_inject_err(ctx->ctxt_to_hw_map, args);
-		rc = 0;
-	} else {
-		CAM_ERR(CAM_CTXT, "hw_intf cb absent for dev hdl: %lld, ctx id: %lld",
-			ctx->dev_hdl, ctx->ctx_id);
+	inject_evt = inject_evt_arg;
+	evt_params = inject_evt->evt_params;
+
+	switch (evt_params->inject_id) {
+	case CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE:
+		rc = cam_context_apply_buf_done_err_injection(ctx, inject_evt);
+	case CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE:
+		evt_notify_type = evt_params->u.evt_notify.evt_notify_type;
+		switch (evt_notify_type) {
+		case V4L_EVENT_CAM_REQ_MGR_ERROR:
+			rc = cam_context_apply_error_event_injection(ctx, evt_params);
+			break;
+		case V4L_EVENT_CAM_REQ_MGR_PF_ERROR:
+			rc = cam_context_apply_pf_evt_injection(ctx, evt_params);
+			break;
+		case V4L_EVENT_CAM_REQ_MGR_NODE_EVENT:
+			rc = cam_context_apply_node_event_injection(ctx, evt_params);
+			break;
+		}
 	}
 
 	return rc;

+ 1 - 1
drivers/cam_core/cam_context_utils.h

@@ -39,5 +39,5 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
 size_t cam_context_parse_config_cmd(struct cam_context *ctx, struct cam_config_dev_cmd *cmd,
 	struct cam_packet **packet);
 int cam_context_mini_dump(struct cam_context *ctx, void *args);
-int cam_context_err_to_hw(struct cam_context *ctx, void *args);
+int cam_context_apply_evt_injection(struct cam_context *ctx, void *inject_evt_arg);
 #endif /* _CAM_CONTEXT_UTILS_H_ */

+ 70 - 12
drivers/cam_core/cam_hw_mgr_intf.h

@@ -546,18 +546,76 @@ struct cam_hw_mini_dump_info {
 };
 
 /**
- * cam_hw_err_param - cam hHW error injection parameters
+ * cam_hw_inject_err_evt_param - error evt injection parameters
  *
- * @err_type         error type for the injected error
- * @err_code         error code for the injected error
- * @err_req_id       Req Id for which the error is injected
- * @is_valid         bool flag to indicate if error injection is enabled for a context
+ * @err_type:         error type for the injected err evt
+ * @err_code:         error code for the injected err evt
  */
-struct cam_hw_err_param {
-	uint32_t   err_type;
-	uint32_t   err_code;
-	uint64_t   err_req_id;
-	bool       is_valid;
+struct cam_hw_inject_err_evt_param {
+	uint32_t err_type;
+	uint32_t err_code;
+};
+
+/**
+ * cam_hw_inject_node_evt_param - node evt injection parameters
+ * @event_type:       event type for the injected node evt
+ * @event_cause:      event cause for the injected node evt
+ */
+struct cam_hw_inject_node_evt_param {
+	uint32_t event_type;
+	uint32_t event_cause;
+};
+
+/**
+ * cam_hw_inject_pf_evt_param - pf evt injection parameters
+ *
+ * @ctx_found:        flag to indicate if page fault notification sent with ctx or not
+ */
+struct cam_hw_inject_pf_evt_param {
+	bool ctx_found;
+};
+
+/**
+ * cam_hw_inject_evt_notification_param - notify event parameters
+ *
+ * @evt_notify_type:   type of event notification
+ * @u:                 union which can be either error event/Page Fault event/Node event
+ */
+
+struct cam_hw_inject_evt_notification_param {
+	uint32_t evt_notify_type;
+	union {
+		struct cam_hw_inject_err_evt_param  err_evt_params;
+		struct cam_hw_inject_pf_evt_param   pf_evt_params;
+		struct cam_hw_inject_node_evt_param node_evt_params;
+	} u;
+};
+
+/**
+ * cam_hw_inject_buffer_error_param - buffer error injection parameters
+ *
+ * @sync_error:        sync error code
+ */
+struct cam_hw_inject_buffer_error_param {
+	uint32_t sync_error;
+};
+
+/**
+ * cam_hw_inject_evt_param - CRM event injection parameters
+ *
+ * @inject_id:        generic inject identifier
+ * @req_id:           Req Id for which the event is injected
+ * @u:                union which can be either buffer done error/event notification
+ * @is_valid:         bool flag to indicate if event injection is enabled for a context
+ */
+struct cam_hw_inject_evt_param {
+	uint8_t inject_id;
+	uint64_t req_id;
+	union {
+		struct cam_hw_inject_buffer_error_param buf_err_evt;
+		struct cam_hw_inject_evt_notification_param evt_notify;
+	} u;
+	bool is_valid;
 };
 
 /**
@@ -590,7 +648,7 @@ struct cam_hw_err_param {
  * @hw_reset:                  Function pointer for HW reset
  * @hw_dump:                   Function pointer for HW dump
  * @hw_recovery:               Function pointer for HW recovery callback
- * @hw_inject_err              Function pointer for HW error injection callback
+ * @hw_inject_evt:             Function pointer for HW event injection callback
  *
  */
 struct cam_hw_mgr_intf {
@@ -614,7 +672,7 @@ struct cam_hw_mgr_intf {
 	int (*hw_reset)(void *hw_priv, void *hw_reset_args);
 	int (*hw_dump)(void *hw_priv, void *hw_dump_args);
 	int (*hw_recovery)(void *hw_priv, void *hw_recovery_args);
-	void (*hw_inject_err)(void *hw_priv, void *hw_err_inject_args);
+	void (*hw_inject_evt)(void *hw_priv, void *evt_args);
 };
 
 #endif /* _CAM_HW_MGR_INTF_H_ */

+ 103 - 29
drivers/cam_icp/cam_icp_context.c

@@ -107,12 +107,12 @@ static int __cam_icp_release_dev_in_acquired(struct cam_context *ctx,
 {
 	int rc;
 
+	cam_common_release_evt_params(ctx->dev_hdl);
+
 	rc = cam_context_release_dev_to_hw(ctx, cmd);
 	if (rc)
 		CAM_ERR(CAM_ICP, "Unable to release device");
 
-	cam_common_release_err_params(ctx->dev_hdl);
-
 	ctx->state = CAM_CTX_AVAILABLE;
 	trace_cam_context_state("ICP", ctx);
 	return rc;
@@ -303,13 +303,19 @@ static int cam_icp_ctx_handle_buf_done_in_ready(void *ctx, void *done_evt_data)
 	return cam_context_buf_done_from_hw(ctx, buf_done->buf_done_data, buf_done->evt_id);
 }
 
+static int cam_icp_ctx_handle_error_inducement(void *ctx, void *inject_evt_arg)
+{
+	return cam_context_apply_evt_injection(ctx, inject_evt_arg);
+}
+
 static int __cam_icp_ctx_handle_hw_event(void *ctx,
 	uint32_t evt_id, void *evt_data)
 {
 	int rc;
 
 	if (!ctx || !evt_data) {
-		CAM_ERR(CAM_ICP, "Invalid ctx and event data");
+		CAM_ERR(CAM_ICP, "Invalid ctx  %s and event data %s",
+			CAM_IS_NULL_TO_STR(ctx), CAM_IS_NULL_TO_STR(evt_data));
 		return -EINVAL;
 	}
 
@@ -320,52 +326,120 @@ static int __cam_icp_ctx_handle_hw_event(void *ctx,
 	case CAM_ICP_EVT_ID_ERROR:
 		rc = cam_icp_ctx_handle_fatal_error(ctx, evt_data);
 		break;
+	case CAM_ICP_EVT_ID_INJECT_EVENT:
+		rc = cam_icp_ctx_handle_error_inducement(ctx, evt_data);
+		break;
 	default:
-		CAM_ERR(CAM_ICP, "Invalid event id: %d", evt_id);
+		CAM_ERR(CAM_ICP, "Invalid event id: %u", evt_id);
 		rc = -EINVAL;
 	}
 
 	return rc;
 }
 
-static int cam_icp_context_inject_error(void *context, void *err_param)
+static int cam_icp_context_validate_event_notify_injection(struct cam_context *ctx,
+	struct cam_hw_inject_evt_param *evt_params)
 {
 	int rc = 0;
-	uint32_t err_code;
-	uint32_t err_type;
+	uint32_t evt_type;
 	uint64_t req_id;
-	struct cam_context *ctx = (struct cam_context *)context;
 
-	if (!err_param) {
-		CAM_ERR(CAM_ICP, "err_params is not valid");
-		return -EINVAL;
-	}
+	req_id   = evt_params->req_id;
+	evt_type = evt_params->u.evt_notify.evt_notify_type;
 
-	err_code = ((struct cam_err_inject_param *)err_param)->err_code;
-	err_type = ((struct cam_err_inject_param *)err_param)->err_type;
-	req_id = ((struct cam_err_inject_param *)err_param)->req_id;
+	switch (evt_type) {
+	case V4L_EVENT_CAM_REQ_MGR_ERROR: {
+		struct cam_hw_inject_err_evt_param *err_evt_params =
+			&evt_params->u.evt_notify.u.err_evt_params;
 
-	switch (err_type) {
-	case CAM_SYNC_STATE_SIGNALED_ERROR:
-		switch (err_code) {
-		case CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE:
-		case CAM_SYNC_ICP_EVENT_CONFIG_ERR:
+		switch (err_evt_params->err_type) {
+		case CAM_REQ_MGR_ERROR_TYPE_RECOVERY:
+		case CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY:
 			break;
 		default:
-			CAM_ERR(CAM_ICP, "ICP Error code %d not supported!", err_code);
+			CAM_ERR(CAM_ICP,
+				"Invalid error type: %u for error event injection err code: %u req id: %llu ctx id: %u dev hdl: %d",
+				err_evt_params->err_type, err_evt_params->err_code,
+				req_id, ctx->ctx_id, ctx->dev_hdl);
 			return -EINVAL;
 		}
+
+		CAM_INFO(CAM_ICP,
+			"Inject ERR evt: err code: %u err type: %u req id: %llu ctx id: %u dev hdl: %d",
+			err_evt_params->err_code, err_evt_params->err_type,
+			req_id, ctx->ctx_id, ctx->dev_hdl);
 		break;
+	}
+	case V4L_EVENT_CAM_REQ_MGR_PF_ERROR: {
+		struct cam_hw_inject_pf_evt_param *pf_evt_params =
+			&evt_params->u.evt_notify.u.pf_evt_params;
+		bool non_fatal_en;
+
+		rc = cam_smmu_is_cb_non_fatal_fault_en(ctx->img_iommu_hdl, &non_fatal_en);
+		if (rc) {
+			CAM_ERR(CAM_ICP,
+				"Fail to query whether device's cb has non-fatal enabled rc: %d",
+				rc);
+			return rc;
+		}
+
+		if (!non_fatal_en) {
+			CAM_ERR(CAM_ICP,
+				"Fail to inject page fault event notification. Page fault is fatal for ICP");
+			return -EINVAL;
+		}
+
+		CAM_INFO(CAM_ICP,
+			"Inject PF evt: req_id: %llu ctx id: %u dev hdl: %d ctx found: %hhu",
+			req_id, ctx->ctx_id, ctx->dev_hdl, pf_evt_params->ctx_found);
+		break;
+	}
 	default:
-		CAM_ERR(CAM_ICP, "ICP Error type: %d not supported!", err_code);
+		CAM_ERR(CAM_ICP, "Event notification type not supported: %u", evt_type);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_icp_context_inject_evt(void *context, void *evt_args)
+{
+	struct cam_context *ctx = context;
+	struct cam_hw_inject_evt_param *evt_params = NULL;
+	struct cam_hw_inject_buffer_error_param *buf_err_params = NULL;
+	int rc = 0;
+
+	if (!ctx || !evt_args) {
+		CAM_ERR(CAM_ICP,
+			"invalid params ctx %s event args %s",
+			CAM_IS_NULL_TO_STR(ctx), CAM_IS_NULL_TO_STR(evt_args));
 		return -EINVAL;
 	}
 
-	CAM_INFO(CAM_ICP,
-		"Err inject params: err_code: %u err_type: %u, to dev_hdl: %lld",
-		err_code, err_type, ctx->dev_hdl);
+	evt_params = (struct cam_hw_inject_evt_param *)evt_args;
+
+	if (evt_params->inject_id == CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE) {
+		buf_err_params = &evt_params->u.buf_err_evt;
+		if (buf_err_params->sync_error > CAM_SYNC_ICP_EVENT_START ||
+			buf_err_params->sync_error < CAM_SYNC_ICP_EVENT_END) {
+			CAM_INFO(CAM_ICP, "Inject buffer sync error %u ctx id: %u req id %llu",
+				buf_err_params->sync_error, ctx->ctx_id, evt_params->req_id);
+		} else {
+			CAM_ERR(CAM_ICP, "Invalid buffer sync error %u ctx id: %u req id %llu",
+				buf_err_params->sync_error, ctx->ctx_id, evt_params->req_id);
+			return -EINVAL;
+		}
+	} else {
+		rc = cam_icp_context_validate_event_notify_injection(ctx, evt_params);
+		if (rc) {
+			CAM_ERR(CAM_ICP,
+				"Event notification injection failed validation rc: %d", rc);
+			return -EINVAL;
+		}
+	}
 
-	rc = cam_context_err_to_hw(ctx, err_param);
+	if (ctx->hw_mgr_intf->hw_inject_evt)
+		ctx->hw_mgr_intf->hw_inject_evt(ctx->ctxt_to_hw_map, evt_args);
 
 	return rc;
 }
@@ -400,7 +474,7 @@ static struct cam_ctx_ops
 		.irq_ops = __cam_icp_ctx_handle_hw_event,
 		.pagefault_ops = cam_icp_context_dump_active_request,
 		.mini_dump_ops = cam_icp_context_mini_dump,
-		.err_inject_ops = cam_icp_context_inject_error,
+		.evt_inject_ops = cam_icp_context_inject_evt,
 	},
 	/* Ready */
 	{
@@ -415,7 +489,7 @@ static struct cam_ctx_ops
 		.irq_ops = __cam_icp_ctx_handle_hw_event,
 		.pagefault_ops = cam_icp_context_dump_active_request,
 		.mini_dump_ops = cam_icp_context_mini_dump,
-		.err_inject_ops = cam_icp_context_inject_error,
+		.evt_inject_ops = cam_icp_context_inject_evt,
 	},
 	/* Flushed */
 	{
@@ -428,7 +502,7 @@ static struct cam_ctx_ops
 		.irq_ops = NULL,
 		.pagefault_ops = cam_icp_context_dump_active_request,
 		.mini_dump_ops = cam_icp_context_mini_dump,
-		.err_inject_ops = cam_icp_context_inject_error,
+		.evt_inject_ops = cam_icp_context_inject_evt,
 	},
 };
 

+ 10 - 10
drivers/cam_icp/cam_icp_subdev.c

@@ -53,20 +53,20 @@ static const struct of_device_id cam_icp_dt_match[] = {
 	{}
 };
 
-static int cam_icp_dev_err_inject_cb(void *err_param)
+static int cam_icp_dev_evt_inject_cb(void *inject_args)
 {
-	int i  = 0;
+	struct cam_common_inject_evt_param *inject_params = inject_args;
+	int i;
 
 	for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
-		if (g_icp_dev.ctx[i].dev_hdl ==
-			((struct cam_err_inject_param *)err_param)->dev_hdl) {
-			CAM_INFO(CAM_ICP, "ICP err inject dev_hdl found:%d",
-				g_icp_dev.ctx[i].dev_hdl);
-			cam_context_add_err_inject(&g_icp_dev.ctx[i], err_param);
+		if (g_icp_dev.ctx[i].dev_hdl == inject_params->dev_hdl) {
+			cam_context_add_evt_inject(&g_icp_dev.ctx[i],
+				&inject_params->evt_params);
 			return 0;
 		}
 	}
-	CAM_ERR(CAM_ICP, "No dev hdl found");
+
+	CAM_ERR(CAM_ICP, "No dev hdl found %d", inject_params->dev_hdl);
 	return -ENODEV;
 }
 
@@ -261,8 +261,8 @@ static int cam_icp_component_bind(struct device *dev,
 		goto ctx_fail;
 	}
 
-	cam_common_register_err_inject_cb(cam_icp_dev_err_inject_cb,
-		CAM_COMMON_ERR_INJECT_HW_ICP);
+	cam_common_register_evt_inject_cb(cam_icp_dev_evt_inject_cb,
+		CAM_COMMON_EVT_INJECT_HW_ICP);
 
 	node->sd_handler = cam_icp_subdev_close_internal;
 	cam_smmu_set_client_page_fault_handler(iommu_hdl,

+ 44 - 47
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -2232,31 +2232,24 @@ static const char *cam_icp_error_handle_id_to_type(
 	return name;
 }
 
-static inline void cam_icp_mgr_validate_inject_err(uint64_t current_req_id, uint32_t *event_id,
-		struct cam_hw_done_event_data *buf_data, struct cam_icp_hw_ctx_data *ctx_data)
-{
-	if (ctx_data->err_inject_params.err_req_id == current_req_id) {
-		switch (ctx_data->err_inject_params.err_code) {
-		case CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE:
-			*event_id = CAM_CTX_EVT_ID_ERROR;
-			buf_data->evt_param = CAM_SYNC_ICP_EVENT_FRAME_PROCESS_FAILURE;
-			break;
-		case CAM_SYNC_ICP_EVENT_CONFIG_ERR:
-			*event_id = CAM_CTX_EVT_ID_ERROR;
-			buf_data->evt_param = CAM_SYNC_ICP_EVENT_CONFIG_ERR;
-			break;
-		default:
-			CAM_INFO(CAM_ICP, "ICP error code not supported: %d",
-				ctx_data->err_inject_params.err_code);
-			return;
-		}
-	} else
-		return;
+static inline void cam_icp_mgr_apply_evt_injection(struct cam_hw_done_event_data *buf_done_data,
+	struct cam_icp_hw_ctx_data *ctx_data, bool *signal_fence_buffer)
+{
+	struct cam_hw_inject_evt_param *evt_params = &ctx_data->evt_inject_params;
+	struct cam_common_evt_inject_data inject_evt;
 
-	CAM_INFO(CAM_ICP, "ICP Err Induced! err_code: %u, req_id: %llu",
-		ctx_data->err_inject_params.err_code, current_req_id);
+	inject_evt.buf_done_data = buf_done_data;
+	inject_evt.evt_params = evt_params;
 
-	memset(&(ctx_data->err_inject_params), 0, sizeof(struct cam_hw_err_param));
+	if (ctx_data->ctxt_event_cb)
+		ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_ICP_EVT_ID_INJECT_EVENT,
+			&inject_evt);
+
+	if (ctx_data->evt_inject_params.inject_id ==
+		CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE)
+		*signal_fence_buffer = false;
+
+	evt_params->is_valid = false;
 }
 
 static void cam_icp_mgr_dump_active_req_info(void)
@@ -2332,6 +2325,7 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
 	struct cam_icp_hw_error_evt_data icp_err_evt = {0};
 	uint32_t clk_type, event_id;
 	struct cam_hangdump_mem_regions *mem_regions = NULL;
+	bool signal_fence_buffer = true;
 
 	ioconfig_ack = (struct hfi_msg_dev_async_ack *)msg_ptr;
 	request_id = ioconfig_ack->user_data2;
@@ -2419,19 +2413,18 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
 		"[%s]: BufDone Req %llu event_id %d",
 		ctx_data->ctx_id_string, hfi_frame_process->request_id[idx], event_id);
 
-	if (ctx_data->err_inject_params.is_valid)
-		cam_icp_mgr_validate_inject_err(request_id, &event_id, &buf_data, ctx_data);
-
 	buf_data.request_id = hfi_frame_process->request_id[idx];
-	icp_done_evt.evt_id = event_id;
-	icp_done_evt.buf_done_data = &buf_data;
-	if (ctx_data->ctxt_event_cb)
-		ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_ICP_EVT_ID_BUF_DONE,
-			&icp_done_evt);
-	else
-		CAM_ERR(CAM_ICP,
-			"Event callback invalid for ctx: %u [%s] failed to signal req: %llu",
-			ctx_data->ctx_id, ctx_data->ctx_id_string, buf_data.request_id);
+	if ((ctx_data->evt_inject_params.is_valid) &&
+		(ctx_data->evt_inject_params.req_id == request_id))
+		cam_icp_mgr_apply_evt_injection(&buf_data, ctx_data, &signal_fence_buffer);
+
+	if (signal_fence_buffer) {
+		icp_done_evt.evt_id = event_id;
+		icp_done_evt.buf_done_data = &buf_data;
+		if (ctx_data->ctxt_event_cb)
+			ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_ICP_EVT_ID_BUF_DONE,
+				&icp_done_evt);
+	}
 
 	hfi_frame_process->request_id[idx] = 0;
 	if (ctx_data->hfi_frame_process.in_resource[idx] > 0) {
@@ -3992,8 +3985,9 @@ static int cam_icp_mgr_release_ctx(struct cam_icp_hw_mgr *hw_mgr, int ctx_id)
 		hw_mgr->ctx_data[ctx_id].ctx_id_string, perf_stats->total_requests,
 		perf_stats->total_requests ?
 		(perf_stats->total_resp_time / perf_stats->total_requests) : 0);
-	memset(&(hw_mgr->ctx_data[ctx_id].err_inject_params), 0,
-		sizeof(struct cam_hw_err_param));
+
+	memset(&hw_mgr->ctx_data[ctx_id].evt_inject_params, 0,
+		sizeof(struct cam_hw_inject_evt_param));
 	cam_icp_remove_ctx_bw(hw_mgr, &hw_mgr->ctx_data[ctx_id]);
 	if (hw_mgr->ctx_data[ctx_id].state !=
 		CAM_ICP_CTX_STATE_ACQUIRED) {
@@ -6953,17 +6947,20 @@ static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 	return rc;
 }
 
-static void cam_icp_mgr_inject_err(void *hw_mgr_priv, void *hw_err_inject_args)
+static void cam_icp_mgr_inject_evt(void *hw_mgr_priv, void *evt_args)
 {
-	struct cam_icp_hw_ctx_data *ctx_data = hw_mgr_priv;
+	struct cam_icp_hw_ctx_data *ctx_data       = hw_mgr_priv;
+	struct cam_hw_inject_evt_param *evt_params = evt_args;
+
+	if (!ctx_data || !evt_params) {
+		CAM_ERR(CAM_ICP, "Invalid params ctx data %s event params %s",
+			CAM_IS_NULL_TO_STR(ctx_data), CAM_IS_NULL_TO_STR(evt_params));
+		return;
+	}
+
+	memcpy(&ctx_data->evt_inject_params, evt_params, sizeof(struct cam_hw_inject_evt_param));
 
-	ctx_data->err_inject_params.err_code   = ((struct cam_err_inject_param *)
-		hw_err_inject_args)->err_code;
-	ctx_data->err_inject_params.err_type   = ((struct cam_err_inject_param *)
-		hw_err_inject_args)->err_type;
-	ctx_data->err_inject_params.err_req_id = ((struct cam_err_inject_param *)
-		hw_err_inject_args)->req_id;
-	ctx_data->err_inject_params.is_valid   = true;
+	ctx_data->evt_inject_params.is_valid = true;
 }
 
 int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
@@ -6995,7 +6992,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
 	hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush;
 	hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd;
 	hw_mgr_intf->hw_dump = cam_icp_mgr_hw_dump;
-	hw_mgr_intf->hw_inject_err = cam_icp_mgr_inject_err;
+	hw_mgr_intf->hw_inject_evt = cam_icp_mgr_inject_evt;
 
 	icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE;
 	icp_hw_mgr.mini_dump_cb = mini_dump_cb;

+ 2 - 2
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h

@@ -283,8 +283,8 @@ struct cam_ctx_clk_info {
  * @watch_dog_reset_counter: Counter for watch dog reset
  * @icp_dev_io_info: io config resource
  * @last_flush_req: last flush req for this ctx
- * @err_inject_params: Error injection data for hw_mgr_ctx
  * @perf_stats: performance statistics info
+ * @evt_inject_params: Event injection data for hw_mgr_ctx
  * @unified_dev_type: Unified dev type which does not hold any priority info.
  *                    It's either IPE/BPS
  * @abort_timed_out: Indicates if abort timed out
@@ -311,8 +311,8 @@ struct cam_icp_hw_ctx_data {
 	struct cam_icp_acquire_dev_info icp_dev_io_info;
 	uint64_t last_flush_req;
 	char ctx_id_string[128];
-	struct cam_hw_err_param err_inject_params;
 	struct cam_icp_ctx_perf_stats perf_stats;
+	struct cam_hw_inject_evt_param evt_inject_params;
 	uint32_t unified_dev_type;
 	bool abort_timed_out;
 };

+ 1 - 0
drivers/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h

@@ -34,6 +34,7 @@
 enum cam_icp_hw_event_type {
 	CAM_ICP_EVT_ID_BUF_DONE,
 	CAM_ICP_EVT_ID_ERROR,
+	CAM_ICP_EVT_ID_INJECT_EVENT,
 };
 
 enum cam_icp_hw_error_type {

+ 103 - 62
drivers/cam_isp/cam_isp_context.c

@@ -4301,22 +4301,22 @@ static struct cam_isp_ctx_irq_ops
 	},
 };
 
-static inline int cam_isp_context_apply_error(struct cam_hw_err_param *err_params,
-	uint64_t current_req_id, struct cam_context *ctx)
+static inline int cam_isp_context_apply_evt_injection(struct cam_context *ctx)
 {
-	int rc = 0;
+	struct cam_isp_context *ctx_isp = ctx->ctx_priv;
+	struct cam_hw_inject_evt_param *evt_inject_params = &ctx_isp->evt_inject_params;
+	struct cam_common_evt_inject_data inject_evt = {0};
+	int rc;
 
-	if (err_params->err_req_id == current_req_id) {
-		CAM_INFO(CAM_ISP,
-			"Err inject for req: %llu, err_code: %d, err_type: %d ctx id: %d",
-			current_req_id, err_params->err_code, err_params->err_type, ctx->ctx_id);
+	inject_evt.evt_params = evt_inject_params;
+	rc = cam_context_apply_evt_injection(ctx, &inject_evt);
+	if (rc)
+		CAM_ERR(CAM_ISP, "Fail to apply event injection ctx_id: %u req_id: %u",
+			ctx->ctx_id, evt_inject_params->req_id);
 
-		__cam_isp_ctx_notify_v4l2_error_event(err_params->err_type, err_params->err_code,
-			current_req_id, ctx);
-		memset(err_params, 0, sizeof(struct cam_hw_err_param));
-		return rc;
-	}
-	return -EINVAL;
+	evt_inject_params->is_valid = false;
+
+	return rc;
 }
 
 static int __cam_isp_ctx_apply_req_in_activated_state(
@@ -4452,9 +4452,9 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
 	cfg.reapply_type = req_isp->reapply_type;
 	cfg.cdm_reset_before_apply = req_isp->cdm_reset_before_apply;
 
-	if (ctx_isp->err_inject_params.is_valid) {
-		rc = cam_isp_context_apply_error(&(ctx_isp->err_inject_params),
-			req->request_id, ctx_isp->base);
+	if ((ctx_isp->evt_inject_params.is_valid) &&
+		(req->request_id == ctx_isp->evt_inject_params.req_id)) {
+		rc = cam_isp_context_apply_evt_injection(ctx_isp->base);
 		if (!rc)
 			goto end;
 	}
@@ -5958,8 +5958,8 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
 		ctx_isp->hw_ctx = NULL;
 	}
 
-	cam_common_release_err_params(ctx->dev_hdl);
-	memset(&(ctx_isp->err_inject_params), 0, sizeof(struct cam_hw_err_param));
+	cam_common_release_evt_params(ctx->dev_hdl);
+	memset(&ctx_isp->evt_inject_params, 0, sizeof(struct cam_hw_inject_evt_param));
 
 	ctx->session_hdl = -1;
 	ctx->dev_hdl = -1;
@@ -7779,65 +7779,106 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context,
 	return rc;
 }
 
-static int cam_isp_context_inject_error(void *context, void *err_param)
+static int cam_isp_context_validate_event_notify_injection(struct cam_context *ctx,
+	struct cam_hw_inject_evt_param *evt_params)
 {
 	int rc = 0;
-	struct cam_context *ctx = (struct cam_context *)context;
-	struct cam_isp_context *ctx_isp = ctx->ctx_priv;
+	uint32_t evt_type;
 	uint64_t req_id;
-	uint32_t err_code;
-	uint32_t err_type;
 
-	if (!err_param) {
-		CAM_ERR(CAM_ISP, "err_param not valid");
-		return -EINVAL;
-	}
+	req_id   = evt_params->req_id;
+	evt_type = evt_params->u.evt_notify.evt_notify_type;
 
-	req_id     = ((struct cam_err_inject_param *)err_param)->req_id;
-	err_type   = ((struct cam_err_inject_param *)err_param)->err_type;
-	err_code   = ((struct cam_err_inject_param *)err_param)->err_code;
+	switch (evt_type) {
+	case V4L_EVENT_CAM_REQ_MGR_ERROR: {
+		struct cam_hw_inject_err_evt_param *err_evt_params =
+			&evt_params->u.evt_notify.u.err_evt_params;
 
-	switch (err_type) {
-	case CAM_REQ_MGR_ERROR_TYPE_RECOVERY:
-		switch (err_code) {
-		case CAM_REQ_MGR_LINK_STALLED_ERROR:
-		case CAM_REQ_MGR_CSID_FIFO_OVERFLOW_ERROR:
-		case CAM_REQ_MGR_CSID_RECOVERY_OVERFLOW_ERROR:
-		case CAM_REQ_MGR_CSID_PIXEL_COUNT_MISMATCH:
-		case CAM_REQ_MGR_CSID_ERR_ON_SENSOR_SWITCHING:
+		switch (err_evt_params->err_type) {
+		case CAM_REQ_MGR_ERROR_TYPE_RECOVERY:
+		case CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE:
+		case CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY:
+		case CAM_REQ_MGR_WARN_TYPE_KMD_RECOVERY:
 			break;
 		default:
-			CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
+			CAM_ERR(CAM_ISP,
+				"Invalid error type: %u for error event injection err type: %u req id: %llu ctx id: %u dev hdl: %d",
+				err_evt_params->err_type, err_evt_params->err_code,
+				req_id, ctx->ctx_id, ctx->dev_hdl);
 			return -EINVAL;
 		}
+
+		CAM_INFO(CAM_ISP,
+			"Inject ERR evt: err code: %u err type: %u req id: %llu ctx id: %u dev hdl: %d",
+			err_evt_params->err_code, err_evt_params->err_type,
+			req_id, ctx->ctx_id, ctx->dev_hdl);
 		break;
-	case CAM_REQ_MGR_ERROR_TYPE_FULL_RECOVERY:
-		switch (err_code) {
-		case CAM_REQ_MGR_CSID_FATAL_ERROR:
-			break;
-		default:
-			CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
+	}
+	case V4L_EVENT_CAM_REQ_MGR_PF_ERROR: {
+		struct cam_hw_inject_pf_evt_param *pf_evt_params =
+			&evt_params->u.evt_notify.u.pf_evt_params;
+		bool non_fatal_en;
+
+		rc = cam_smmu_is_cb_non_fatal_fault_en(ctx->img_iommu_hdl, &non_fatal_en);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"Fail to query whether device's cb has non-fatal enabled rc:%d",
+				rc);
+			return rc;
+		}
+
+		if (!non_fatal_en) {
+			CAM_ERR(CAM_ISP,
+				"Fail to inject page fault event notification. Page fault is fatal for ISP");
 			return -EINVAL;
 		}
+
+		CAM_INFO(CAM_ISP,
+			"Inject PF evt: req_id: %llu ctx id: %u dev hdl: %d ctx found: %hhu",
+			req_id, ctx->ctx_id, ctx->dev_hdl, pf_evt_params->ctx_found);
 		break;
-	case CAM_REQ_MGR_ERROR_TYPE_SOF_FREEZE:
-		err_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR;
-		break;
-	case CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT:
-		err_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR;
-		break;
+	}
 	default:
-		CAM_ERR(CAM_ISP, "err type not supported %d", err_type);
+		CAM_ERR(CAM_ISP, "Event notification type not supported: %u", evt_type);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_isp_context_inject_evt(void *context, void *evt_args)
+{
+	struct cam_context *ctx = context;
+	struct cam_isp_context *ctx_isp = NULL;
+	struct cam_hw_inject_evt_param *evt_params = evt_args;
+	int rc = 0;
+
+	if (!ctx || !evt_args) {
+		CAM_ERR(CAM_ISP,
+			"Invalid params ctx %s event args %s",
+			CAM_IS_NULL_TO_STR(ctx), CAM_IS_NULL_TO_STR(evt_args));
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_ISP, "inject err isp code: %d type: %d ctx id: %d",
-		err_code, err_type, ctx->ctx_id);
+	ctx_isp = ctx->ctx_priv;
+	if (evt_params->inject_id == CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE) {
+		rc = cam_isp_context_validate_event_notify_injection(ctx, evt_params);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"Event notification injection failed validation rc: %d", rc);
+			return rc;
+		}
+	} else {
+		CAM_ERR(CAM_ISP, "Buffer done err injection %u not supported by ISP",
+			evt_params->inject_id);
+		return -EINVAL;
+	}
+
+
+	memcpy(&ctx_isp->evt_inject_params, evt_params,
+		sizeof(struct cam_hw_inject_evt_param));
 
-	ctx_isp->err_inject_params.err_code = err_code;
-	ctx_isp->err_inject_params.err_type = err_type;
-	ctx_isp->err_inject_params.err_req_id   = req_id;
-	ctx_isp->err_inject_params.is_valid = true;
+	ctx_isp->evt_inject_params.is_valid = true;
 
 	return rc;
 }
@@ -7879,7 +7920,7 @@ static struct cam_ctx_ops
 		.irq_ops = NULL,
 		.pagefault_ops = cam_isp_context_dump_requests,
 		.dumpinfo_ops = cam_isp_context_info_dump,
-		.err_inject_ops = cam_isp_context_inject_error,
+		.evt_inject_ops = cam_isp_context_inject_evt,
 	},
 	/* Ready */
 	{
@@ -7898,7 +7939,7 @@ static struct cam_ctx_ops
 		.irq_ops = NULL,
 		.pagefault_ops = cam_isp_context_dump_requests,
 		.dumpinfo_ops = cam_isp_context_info_dump,
-		.err_inject_ops = cam_isp_context_inject_error,
+		.evt_inject_ops = cam_isp_context_inject_evt,
 	},
 	/* Flushed */
 	{
@@ -7916,7 +7957,7 @@ static struct cam_ctx_ops
 		.irq_ops = NULL,
 		.pagefault_ops = cam_isp_context_dump_requests,
 		.dumpinfo_ops = cam_isp_context_info_dump,
-		.err_inject_ops = cam_isp_context_inject_error,
+		.evt_inject_ops = cam_isp_context_inject_evt,
 	},
 	/* Activated */
 	{
@@ -7940,7 +7981,7 @@ static struct cam_ctx_ops
 		.pagefault_ops = cam_isp_context_dump_requests,
 		.dumpinfo_ops = cam_isp_context_info_dump,
 		.recovery_ops = cam_isp_context_hw_recovery,
-		.err_inject_ops = cam_isp_context_inject_error,
+		.evt_inject_ops = cam_isp_context_inject_evt,
 	},
 };
 

+ 2 - 1
drivers/cam_isp/cam_isp_context.h

@@ -288,6 +288,7 @@ struct cam_isp_context_event_record {
  * @trigger_id:                ID provided by CRM for each ctx on the link
  * @last_bufdone_err_apply_req_id:  last bufdone error apply request id
  * @v4l2_event_sub_ids         contains individual bits representing subscribed v4l2 ids
+ * @evt_inject_params:         event injection parameters
  * @aeb_enabled:               Indicate if stream is for AEB
  * @do_internal_recovery:      Enable KMD halt/reset/resume internal recovery
  *
@@ -345,7 +346,7 @@ struct cam_isp_context {
 	int32_t                               trigger_id;
 	int64_t                               last_bufdone_err_apply_req_id;
 	uint32_t                              v4l2_event_sub_ids;
-	struct cam_hw_err_param              err_inject_params;
+	struct cam_hw_inject_evt_param        evt_inject_params;
 	bool                                  aeb_enabled;
 	bool                                  do_internal_recovery;
 };

+ 10 - 8
drivers/cam_isp/cam_isp_dev.c

@@ -25,18 +25,20 @@
 
 static struct cam_isp_dev g_isp_dev;
 
-static int cam_isp_dev_err_inject_cb(void *err_param)
+static int cam_isp_dev_evt_inject_cb(void *inject_args)
 {
-	int i  = 0;
+	struct cam_common_inject_evt_param *inject_params = inject_args;
+	int i;
 
 	for (i = 0; i < g_isp_dev.max_context; i++) {
-		if ((g_isp_dev.ctx[i].dev_hdl) ==
-			((struct cam_err_inject_param *)err_param)->dev_hdl) {
-			cam_context_add_err_inject(&g_isp_dev.ctx[i], err_param);
+		if (g_isp_dev.ctx[i].dev_hdl == inject_params->dev_hdl) {
+			cam_context_add_evt_inject(&g_isp_dev.ctx[i],
+				&inject_params->evt_params);
 			return 0;
 		}
 	}
-	CAM_ERR(CAM_ISP, "no dev hdl found for IFE");
+
+	CAM_ERR(CAM_ISP, "No dev hdl found %d", inject_params->dev_hdl);
 	return -ENODEV;
 }
 
@@ -217,8 +219,8 @@ static int cam_isp_dev_component_bind(struct device *dev,
 		}
 	}
 
-	cam_common_register_err_inject_cb(cam_isp_dev_err_inject_cb,
-		CAM_COMMON_ERR_INJECT_HW_ISP);
+	cam_common_register_evt_inject_cb(cam_isp_dev_evt_inject_cb,
+		CAM_COMMON_EVT_INJECT_HW_ISP);
 
 	rc = cam_node_init(node, &hw_mgr_intf, g_isp_dev.ctx,
 			g_isp_dev.max_context, CAM_ISP_DEV_NAME);

+ 125 - 36
drivers/cam_jpeg/cam_jpeg_context.c

@@ -15,6 +15,7 @@
 #include "cam_context_utils.h"
 #include "cam_debug_util.h"
 #include "cam_packet_util.h"
+#include "cam_jpeg_hw_intf.h"
 
 static const char jpeg_dev_name[] = "cam-jpeg";
 
@@ -95,12 +96,12 @@ static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx,
 {
 	int rc;
 
+	cam_common_release_evt_params(ctx->dev_hdl);
+
 	rc = cam_context_release_dev_to_hw(ctx, cmd);
 	if (rc)
 		CAM_ERR(CAM_JPEG, "Unable to release device %d", rc);
 
-	cam_common_release_err_params(ctx->dev_hdl);
-
 	ctx->state = CAM_CTX_AVAILABLE;
 
 	return rc;
@@ -137,10 +138,43 @@ static int __cam_jpeg_ctx_config_dev_in_acquired(struct cam_context *ctx,
 	return cam_context_prepare_dev_to_hw(ctx, cmd);
 }
 
-static int __cam_jpeg_ctx_handle_buf_done_in_acquired(void *ctx,
-	uint32_t evt_id, void *done)
+static int __cam_jpeg_ctx_handle_buf_done_in_acquired(void *ctx, void *done_evt_data)
+{
+	struct cam_jpeg_hw_buf_done_evt_data *buf_done = done_evt_data;
+
+	return cam_context_buf_done_from_hw(ctx, buf_done->buf_done_data,
+		 buf_done->evt_id);
+}
+
+static int __cam_jpeg_ctx_handle_evt_inducement(void *ctx, void *inject_evt_arg)
 {
-	return cam_context_buf_done_from_hw(ctx, done, evt_id);
+	return cam_context_apply_evt_injection(ctx, inject_evt_arg);
+}
+
+static int __cam_jpeg_ctx_handle_hw_event(void *ctx,
+	uint32_t evt_id, void *evt_data)
+{
+	int rc;
+
+	if (!ctx || !evt_data) {
+		CAM_ERR(CAM_JPEG, "Invalid parameters ctx %s evt_data: %s",
+			CAM_IS_NULL_TO_STR(ctx), CAM_IS_NULL_TO_STR(evt_data));
+		return -EINVAL;
+	}
+
+	switch (evt_id) {
+	case CAM_JPEG_EVT_ID_BUF_DONE:
+		rc = __cam_jpeg_ctx_handle_buf_done_in_acquired(ctx, evt_data);
+		break;
+	case CAM_JPEG_EVT_ID_INDUCE_ERR:
+		rc = __cam_jpeg_ctx_handle_evt_inducement(ctx, evt_data);
+		break;
+	default:
+		CAM_ERR(CAM_JPEG, "Invalid event id: %u", evt_id);
+		rc = -EINVAL;
+	}
+
+	return rc;
 }
 
 static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx,
@@ -157,53 +191,108 @@ static int __cam_jpeg_ctx_stop_dev_in_acquired(struct cam_context *ctx,
 	return rc;
 }
 
-static int cam_jpeg_context_inject_error(void *context, void *err_param)
+static int cam_jpeg_context_validate_event_notify_injection(struct cam_context *ctx,
+	struct cam_hw_inject_evt_param *evt_params)
 {
 	int rc = 0;
-	struct cam_context *ctx = (struct cam_context *)context;
+	uint32_t evt_type;
 	uint64_t req_id;
-	uint32_t err_code;
-	uint32_t err_type;
 
-	if (!err_param) {
-		CAM_ERR(CAM_ISP, "err_param not valid");
-		return -EINVAL;
-	}
+	req_id   = evt_params->req_id;
+	evt_type = evt_params->u.evt_notify.evt_notify_type;
 
-	req_id     = ((struct cam_err_inject_param *)err_param)->req_id;
-	err_code   = ((struct cam_err_inject_param *)err_param)->err_code;
-	err_type   = ((struct cam_err_inject_param *)err_param)->err_type;
+	switch (evt_type) {
+	case V4L_EVENT_CAM_REQ_MGR_NODE_EVENT: {
+		struct cam_hw_inject_node_evt_param *node_evt_params =
+			&evt_params->u.evt_notify.u.node_evt_params;
 
-	switch (err_type) {
-	case CAM_REQ_MGR_RETRY_EVENT:
-		switch (err_code) {
-		case CAM_REQ_MGR_JPEG_THUBNAIL_SIZE_ERROR:
+		switch (node_evt_params->event_type) {
+		case CAM_REQ_MGR_RETRY_EVENT:
 			break;
 		default:
-			CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
+			CAM_ERR(CAM_JPEG,
+				"Invalid event type %u for node event injection event cause: %u req id: %llu ctx id: %u dev hdl: %d",
+				node_evt_params->event_type, node_evt_params->event_cause,
+				req_id, ctx->ctx_id, ctx->dev_hdl);
 			return -EINVAL;
 		}
+
+		CAM_INFO(CAM_JPEG,
+			"Inject Node evt: event type: %u event cause: %u req id: %llu ctx id: %u dev hdl: %d",
+			node_evt_params->event_type, node_evt_params->event_cause,
+			req_id, ctx->ctx_id, ctx->dev_hdl);
 		break;
-	case CAM_SYNC_STATE_SIGNALED_ERROR:
-		switch (err_code) {
-		case CAM_SYNC_JPEG_EVENT_INVLD_CMD:
-		case CAM_SYNC_JPEG_EVENT_SET_IRQ_CB:
-		case CAM_SYNC_JPEG_EVENT_HW_RESET_FAILED:
-		case CAM_SYNC_JPEG_EVENT_CDM_CHANGE_BASE_ERR:
-		case CAM_SYNC_JPEG_EVENT_CDM_CONFIG_ERR:
-		case CAM_SYNC_JPEG_EVENT_START_HW_ERR:
-			break;
-		default:
-			CAM_ERR(CAM_ISP, "err code not supported %d", err_code);
+	}
+	case V4L_EVENT_CAM_REQ_MGR_PF_ERROR: {
+		struct cam_hw_inject_pf_evt_param *pf_evt_params =
+			&evt_params->u.evt_notify.u.pf_evt_params;
+		bool non_fatal_en;
+
+		rc = cam_smmu_is_cb_non_fatal_fault_en(ctx->img_iommu_hdl, &non_fatal_en);
+		if (rc) {
+			CAM_ERR(CAM_JPEG,
+				"Fail to query whether device's cb has non-fatal enabled rc: %d",
+				rc);
+			return rc;
+		}
+
+		if (!non_fatal_en) {
+			CAM_ERR(CAM_JPEG,
+				"Fail to inject page fault event notification. Page fault is fatal for JPEG");
 			return -EINVAL;
 		}
+
+		CAM_INFO(CAM_JPEG,
+			"Inject PF evt: req_id: %llu ctx id: %u dev hdl: %d ctx found: %hhu",
+			req_id, ctx->ctx_id, ctx->dev_hdl, pf_evt_params->ctx_found);
 		break;
+	}
 	default:
-		CAM_ERR(CAM_ISP, "err type not supported %d", err_type);
+		CAM_ERR(CAM_JPEG, "Event notification type not supported: %u", evt_type);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_jpeg_context_inject_evt(void *context, void *evt_args)
+{
+	struct cam_context *ctx = context;
+	struct cam_hw_inject_evt_param *evt_params = NULL;
+	struct cam_hw_inject_buffer_error_param *buf_err_params = NULL;
+	int rc = 0;
+
+	if (!ctx || !evt_args) {
+		CAM_ERR(CAM_JPEG,
+			"invalid params ctx %s event args %s",
+			CAM_IS_NULL_TO_STR(ctx), CAM_IS_NULL_TO_STR(evt_args));
 		return -EINVAL;
 	}
 
-	rc = cam_context_err_to_hw(ctx, err_param);
+	evt_params = (struct cam_hw_inject_evt_param *)evt_args;
+
+	if (evt_params->inject_id == CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE) {
+		buf_err_params = &evt_params->u.buf_err_evt;
+		if (buf_err_params->sync_error > CAM_SYNC_JPEG_EVENT_START ||
+			buf_err_params->sync_error < CAM_SYNC_JPEG_EVENT_END) {
+			CAM_INFO(CAM_JPEG, "Inject buffer sync error %u ctx id: %u req id %llu",
+				buf_err_params->sync_error, ctx->ctx_id, evt_params->req_id);
+		} else {
+			CAM_ERR(CAM_JPEG, "Invalid buffer sync error %u",
+				buf_err_params->sync_error);
+			return -EINVAL;
+		}
+	} else {
+		rc = cam_jpeg_context_validate_event_notify_injection(ctx, evt_params);
+		if (rc) {
+			CAM_ERR(CAM_JPEG,
+				"Event notification injection failed validation rc: %d", rc);
+			return rc;
+		}
+	}
+
+	if (ctx->hw_mgr_intf->hw_inject_evt)
+		ctx->hw_mgr_intf->hw_inject_evt(ctx->ctxt_to_hw_map, evt_args);
 
 	return rc;
 }
@@ -236,10 +325,10 @@ static struct cam_ctx_ops
 			.dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired,
 		},
 		.crm_ops = { },
-		.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
+		.irq_ops = __cam_jpeg_ctx_handle_hw_event,
 		.pagefault_ops = cam_jpeg_context_dump_active_request,
 		.mini_dump_ops = cam_jpeg_context_mini_dump,
-		.err_inject_ops = cam_jpeg_context_inject_error,
+		.evt_inject_ops = cam_jpeg_context_inject_evt,
 	},
 	/* Ready */
 	{

+ 10 - 9
drivers/cam_jpeg/cam_jpeg_dev.c

@@ -24,19 +24,20 @@
 
 static struct cam_jpeg_dev g_jpeg_dev;
 
-static int cam_jpeg_dev_err_inject_cb(void *err_param)
+static int cam_jpeg_dev_evt_inject_cb(void *inject_args)
 {
-	int i  = 0;
+	struct cam_common_inject_evt_param *inject_params = inject_args;
+	int i;
 
 	for (i = 0; i < CAM_JPEG_CTX_MAX; i++) {
-		if (g_jpeg_dev.ctx[i].dev_hdl ==
-			((struct cam_err_inject_param *)err_param)->dev_hdl) {
-			CAM_INFO(CAM_ISP, "dev_hdl found:%d", g_jpeg_dev.ctx[i].dev_hdl);
-			cam_context_add_err_inject(&g_jpeg_dev.ctx[i], err_param);
+		if (g_jpeg_dev.ctx[i].dev_hdl == inject_params->dev_hdl) {
+			cam_context_add_evt_inject(&g_jpeg_dev.ctx[i],
+				&inject_params->evt_params);
 			return 0;
 		}
 	}
-	CAM_ERR(CAM_ISP, "no dev hdl found jpeg");
+
+	CAM_ERR(CAM_JPEG, "No dev hdl found %d", inject_params->dev_hdl);
 	return -EINVAL;
 }
 
@@ -191,8 +192,8 @@ static int cam_jpeg_dev_component_bind(struct device *dev,
 		}
 	}
 
-	cam_common_register_err_inject_cb(cam_jpeg_dev_err_inject_cb,
-		CAM_COMMON_ERR_INJECT_HW_JPEG);
+	cam_common_register_evt_inject_cb(cam_jpeg_dev_evt_inject_cb,
+		CAM_COMMON_EVT_INJECT_HW_JPEG);
 
 	rc = cam_node_init(node, &hw_mgr_intf, g_jpeg_dev.ctx, CAM_JPEG_CTX_MAX,
 		CAM_JPEG_DEV_NAME);

+ 55 - 39
drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c

@@ -56,28 +56,23 @@ static int cam_jpeg_insert_cdm_change_base(
 	struct cam_jpeg_hw_ctx_data *ctx_data,
 	struct cam_jpeg_hw_mgr *hw_mgr);
 
-static void cam_jpeg_inject_err(struct cam_jpeg_hw_ctx_data *ctx_data,
-	struct cam_hw_done_event_data *buf_data)
+static void cam_jpeg_mgr_apply_evt_injection(struct cam_hw_done_event_data *buf_done_data,
+	struct cam_jpeg_hw_ctx_data *ctx_data, bool *signal_fence_buffer)
 {
-	struct cam_req_mgr_message v4l2_msg = {0};
-	struct cam_context *cam_ctx         = ctx_data->context_priv;
-
-	if (ctx_data->err_inject_params.err_code == CAM_REQ_MGR_JPEG_THUBNAIL_SIZE_ERROR) {
-		v4l2_msg.session_hdl = cam_ctx->session_hdl;
-		v4l2_msg.u.node_msg.request_id = ctx_data->err_inject_params.err_req_id;
-		v4l2_msg.u.node_msg.link_hdl = cam_ctx->link_hdl;
-		v4l2_msg.u.node_msg.device_hdl = cam_ctx->dev_hdl;
-		v4l2_msg.u.node_msg.event_type = CAM_REQ_MGR_RETRY_EVENT;
-		v4l2_msg.u.node_msg.event_cause =
-			CAM_REQ_MGR_JPEG_THUBNAIL_SIZE_ERROR;
-		cam_req_mgr_notify_message(&v4l2_msg,
-			V4L_EVENT_CAM_REQ_MGR_NODE_EVENT,
-			V4L_EVENT_CAM_REQ_MGR_EVENT);
-	} else {
-		buf_data->evt_param = ctx_data->err_inject_params.err_code;
-	}
+	struct cam_hw_inject_evt_param *evt_inject_params = &ctx_data->evt_inject_params;
+	struct cam_common_evt_inject_data inject_evt;
+
+	inject_evt.buf_done_data = buf_done_data;
+	inject_evt.evt_params = evt_inject_params;
 
-	memset(&(ctx_data->err_inject_params), 0, sizeof(struct cam_hw_err_param));
+	if (ctx_data->ctxt_event_cb)
+		ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_JPEG_EVT_ID_INDUCE_ERR,
+			&inject_evt);
+
+	if (evt_inject_params->inject_id == CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE)
+		*signal_fence_buffer = false;
+
+	evt_inject_params->is_valid = false;
 }
 
 static int cam_jpeg_generic_blob_handler(void *user_data,
@@ -389,6 +384,8 @@ static int cam_jpeg_mgr_bottom_half_irq(void *priv, void *data)
 	struct cam_req_mgr_message                               v4l2_msg = {0};
 	struct cam_ctx_request                                  *req;
 	struct cam_jpeg_misr_dump_args                           misr_args;
+	struct cam_jpeg_hw_buf_done_evt_data                     jpeg_done_evt;
+
 	if (!data || !priv) {
 		CAM_ERR(CAM_JPEG, "Invalid data");
 		return -EINVAL;
@@ -513,8 +510,10 @@ static int cam_jpeg_mgr_bottom_half_irq(void *priv, void *data)
 	}
 
 	buf_data.request_id = jpeg_req->request_id;
-	ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_CTX_EVT_ID_SUCCESS,
-		&buf_data);
+	jpeg_done_evt.evt_id = CAM_CTX_EVT_ID_SUCCESS;
+	jpeg_done_evt.buf_done_data = &buf_data;
+	ctx_data->ctxt_event_cb(ctx_data->context_priv, CAM_JPEG_EVT_ID_BUF_DONE,
+		&jpeg_done_evt);
 
 exit:
 	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_sched_bottom_half;
@@ -641,7 +640,8 @@ static int cam_jpeg_mgr_release_ctx(
 	}
 
 	ctx_data->in_use = false;
-	memset(&(ctx_data->err_inject_params), 0, sizeof(struct cam_hw_err_param));
+	memset(&ctx_data->evt_inject_params, 0, sizeof(struct cam_hw_inject_evt_param));
+
 	mutex_unlock(&ctx_data->ctx_mutex);
 
 	return 0;
@@ -727,6 +727,9 @@ static int cam_jpeg_mgr_process_hw_update_entries(void *priv, void *data)
 	struct cam_jpeg_set_irq_cb                                 irq_cb;
 	struct cam_jpeg_hw_cfg_req                                *p_cfg_req = NULL;
 	struct cam_hw_done_event_data                              buf_data;
+	struct cam_jpeg_hw_buf_done_evt_data                       jpeg_done_evt;
+	bool                                                       event_inject = false;
+	bool                                                       signal_fence_buffer = true;
 
 	task_data = (struct cam_jpeg_process_frame_work_data_t *)data;
 	if (!hw_mgr || !task_data) {
@@ -806,11 +809,12 @@ static int cam_jpeg_mgr_process_hw_update_entries(void *priv, void *data)
 		goto end;
 	}
 
-	if (ctx_data->err_inject_params.is_valid &&
-		ctx_data->err_inject_params.err_req_id == request_id) {
-		cam_jpeg_inject_err(ctx_data, &buf_data);
+	if (ctx_data->evt_inject_params.is_valid &&
+		ctx_data->evt_inject_params.req_id == request_id) {
+		event_inject = true;
 		goto end_callcb;
 	}
+
 	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_sched_bottom_half;
 	irq_cb.irq_cb_data.private_data = (void *)ctx_data;
 	irq_cb.irq_cb_data.jpeg_req = jpeg_req;
@@ -853,8 +857,16 @@ end_callcb:
 			config_args->out_map_entries[i].resource_handle;
 		}
 		buf_data.request_id = (uintptr_t)jpeg_req->request_id;
-		ctx_data->ctxt_event_cb(ctx_data->context_priv,
-			CAM_CTX_EVT_ID_ERROR, &buf_data);
+		if (event_inject)
+			cam_jpeg_mgr_apply_evt_injection(&buf_data, ctx_data,
+				&signal_fence_buffer);
+
+		if (signal_fence_buffer) {
+			jpeg_done_evt.evt_id = CAM_CTX_EVT_ID_ERROR;
+			jpeg_done_evt.buf_done_data = &buf_data;
+			ctx_data->ctxt_event_cb(ctx_data->context_priv,
+				CAM_JPEG_EVT_ID_BUF_DONE, &jpeg_done_evt);
+		}
 	}
 end_unusedev:
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
@@ -2193,17 +2205,21 @@ static int cam_jpeg_mgr_create_debugfs_entry(void)
 	return rc;
 }
 
-static void cam_jpeg_mgr_inject_err(void *hw_mgr_priv, void *hw_err_inject_args)
+static void cam_jpeg_mgr_inject_evt(void *hw_mgr_priv, void *evt_args)
 {
-	struct cam_jpeg_hw_ctx_data *ctx_data = hw_mgr_priv;
-
-	ctx_data->err_inject_params.err_code = ((struct cam_err_inject_param  *)
-		hw_err_inject_args)->err_code;
-	ctx_data->err_inject_params.err_type   = ((struct cam_err_inject_param *)
-		hw_err_inject_args)->err_type;
-	ctx_data->err_inject_params.err_req_id = ((struct cam_err_inject_param *)
-		hw_err_inject_args)->req_id;
-	ctx_data->err_inject_params.is_valid   = true;
+	struct cam_jpeg_hw_ctx_data *ctx_data      = hw_mgr_priv;
+	struct cam_hw_inject_evt_param *evt_params = evt_args;
+
+	if (!ctx_data || !evt_params) {
+		CAM_ERR(CAM_JPEG, "Invalid parameters ctx data %s event params %s",
+			CAM_IS_NULL_TO_STR(ctx_data), CAM_IS_NULL_TO_STR(evt_params));
+		return;
+	}
+
+	memcpy(&ctx_data->evt_inject_params, evt_params,
+		sizeof(struct cam_hw_inject_evt_param));
+
+	ctx_data->evt_inject_params.is_valid = true;
 }
 
 int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
@@ -2233,7 +2249,7 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
 	hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop;
 	hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd;
 	hw_mgr_intf->hw_dump = cam_jpeg_mgr_hw_dump;
-	hw_mgr_intf->hw_inject_err = cam_jpeg_mgr_inject_err;
+	hw_mgr_intf->hw_inject_evt = cam_jpeg_mgr_inject_evt;
 
 	mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
 	spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);

+ 3 - 2
drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef CAM_JPEG_HW_MGR_H
@@ -104,7 +105,7 @@ struct cam_jpeg_hw_cfg_req {
  * @wait_complete: Completion info
  * @cdm_cmd: Cdm cmd submitted for that context.
  * @mini_dump_cb: Mini dump cb
- * @err_inject_params: Error injection params for hw_mgr_ctx
+ * @evt_inject_params: Event injection params for hw_mgr_ctx
  */
 struct cam_jpeg_hw_ctx_data {
 	void *context_priv;
@@ -115,7 +116,7 @@ struct cam_jpeg_hw_ctx_data {
 	struct completion wait_complete;
 	struct cam_cdm_bl_request *cdm_cmd;
 	cam_ctx_mini_dump_cb_func      mini_dump_cb;
-	struct cam_hw_err_param err_inject_params;
+	struct cam_hw_inject_evt_param evt_inject_params;
 };
 
 /**

+ 16 - 0
drivers/cam_jpeg/jpeg_hw/include/cam_jpeg_hw_intf.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef CAM_JPEG_HW_INTF_H
@@ -82,6 +83,16 @@ struct cam_jpeg_misr_dump_args {
 	bool        enable_bug;
 };
 
+/**
+ * struct cam_jpeg_hw_buf_done_evt_data
+ * @buf_done_data:    buf done payload
+ * @evt_id:           event id (success/cancel/error)
+ */
+struct cam_jpeg_hw_buf_done_evt_data {
+	void      *buf_done_data;
+	uint32_t   evt_id;
+};
+
 enum cam_jpeg_cmd_type {
 	CAM_JPEG_CMD_CDM_CFG,
 	CAM_JPEG_CMD_SET_IRQ_CB,
@@ -94,4 +105,9 @@ enum cam_jpeg_cmd_type {
 	CAM_JPEG_CMD_MAX,
 };
 
+enum cam_jpeg_hw_event_type {
+	CAM_JPEG_EVT_ID_BUF_DONE,
+	CAM_JPEG_EVT_ID_INDUCE_ERR,
+};
+
 #endif

+ 21 - 0
drivers/cam_smmu/cam_smmu_api.c

@@ -925,6 +925,27 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain,
 	return -ENOSYS;
 }
 
+int cam_smmu_is_cb_non_fatal_fault_en(int smmu_hdl, bool *non_fatal_en)
+{
+	int idx;
+
+	if (smmu_hdl == HANDLE_INIT) {
+		CAM_ERR(CAM_SMMU, "Invalid iommu handle %d", smmu_hdl);
+		return -EINVAL;
+	}
+
+	idx = GET_SMMU_TABLE_IDX(smmu_hdl);
+	if (idx < 0 || idx >= iommu_cb_set.cb_num) {
+		CAM_ERR(CAM_SMMU,
+			"Invalid handle or idx. idx: %d, hdl: 0x%x", idx, smmu_hdl);
+		return -EINVAL;
+	}
+
+	*non_fatal_en = iommu_cb_set.cb_info[idx].non_fatal_faults_en;
+
+	return 0;
+}
+
 void cam_smmu_reset_cb_page_fault_cnt(void)
 {
 	int idx;

+ 5 - 0
drivers/cam_smmu/cam_smmu_api.h

@@ -468,4 +468,9 @@ bool cam_smmu_need_shared_buffer_padding(void);
  */
 bool cam_smmu_is_expanded_memory(void);
 
+/**
+ * @brief : API to query whether page fault non fatal is enable for a device's context bank
+ */
+int cam_smmu_is_cb_non_fatal_fault_en(int smmu_hdl, bool *non_fatal_en);
+
 #endif /* _CAM_SMMU_API_H_ */

+ 410 - 124
drivers/cam_utils/cam_common_util.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/string.h>
@@ -22,10 +23,13 @@ static  struct cam_common_mini_dump_dev_info g_minidump_dev_info;
 
 #define CAM_PRESIL_POLL_DELAY 20
 
-static struct cam_common_err_inject_info g_err_inject_info;
+static struct cam_common_inject_evt_info g_inject_evt_info;
 
 static uint timeout_multiplier = 1;
 module_param(timeout_multiplier, uint, 0644);
+typedef int (*cam_common_evt_inject_cmd_parse_handler)(
+	struct cam_common_inject_evt_param *inject_params,
+	uint32_t param_counter, char *token);
 
 int cam_common_util_get_string_index(const char **strings,
 	uint32_t num_strings, const char *matching_string, uint32_t *index)
@@ -339,201 +343,483 @@ int cam_common_user_dump_helper(
 	return 0;
 }
 
-int cam_common_register_err_inject_cb(
-	cam_common_err_inject_cb err_inject_cb,
-	enum cam_common_err_inject_hw_id hw_id)
+int cam_common_register_evt_inject_cb(cam_common_evt_inject_cb evt_inject_cb,
+	enum cam_common_evt_inject_hw_id hw_id)
 {
 	int rc = 0;
 
-	if (g_err_inject_info.num_hw_registered >= CAM_COMMON_ERR_INJECT_HW_MAX) {
+	if (g_inject_evt_info.num_hw_registered >= CAM_COMMON_EVT_INJECT_HW_MAX) {
 		CAM_ERR(CAM_UTIL, "No free index available");
 		return -EINVAL;
 	}
 
-	if (!err_inject_cb || hw_id >= CAM_COMMON_ERR_INJECT_HW_MAX) {
-		CAM_ERR(CAM_UTIL, "Invalid params");
+	if (!evt_inject_cb || hw_id >= CAM_COMMON_EVT_INJECT_HW_MAX) {
+		CAM_ERR(CAM_UTIL, "Invalid params evt_inject_cb %s hw_id: %d",
+			CAM_IS_NULL_TO_STR(evt_inject_cb), hw_id);
 		return -EINVAL;
 	}
 
-	g_err_inject_info.err_inject_cb[hw_id] = err_inject_cb;
-	g_err_inject_info.num_hw_registered++;
-	CAM_DBG(CAM_UTIL, "err inject cb registered for HW_id:%d, total registered: %d", hw_id,
-		g_err_inject_info.num_hw_registered);
+	g_inject_evt_info.evt_inject_cb[hw_id] = evt_inject_cb;
+	g_inject_evt_info.num_hw_registered++;
+	CAM_DBG(CAM_UTIL, "Evt inject cb registered for HW_id: %d, total registered: %d", hw_id,
+		g_inject_evt_info.num_hw_registered);
 	return rc;
 }
 
-int cam_common_release_err_params(uint64_t dev_hdl)
+void cam_common_release_evt_params(int32_t dev_hdl)
 {
-	int rc = 0;
 	struct list_head *pos = NULL, *pos_next = NULL;
-	struct cam_err_inject_param *err_param;
+	struct cam_common_inject_evt_param *inject_params;
+
+	if (!g_inject_evt_info.is_list_initialised)
+		return;
+
+	if (list_empty(&g_inject_evt_info.active_evt_ctx_list)) {
+		CAM_DBG(CAM_UTIL, "Event injection list is initialized but empty");
+		return;
+	}
+
+	list_for_each_safe(pos, pos_next, &g_inject_evt_info.active_evt_ctx_list) {
+		inject_params = list_entry(pos, struct cam_common_inject_evt_param, list);
+		if (inject_params->dev_hdl == dev_hdl) {
+			CAM_INFO(CAM_UTIL, "entry deleted for %d dev hdl", dev_hdl);
+			list_del(pos);
+			kfree(inject_params);
+		}
+	}
+}
 
-	if (!g_err_inject_info.is_list_initialised)
+static inline int cam_common_evt_inject_get_hw_id(uint8_t *hw_id, char *token)
+{
+	if (strcmp(token, CAM_COMMON_IFE_NODE) == 0)
+		*hw_id = CAM_COMMON_EVT_INJECT_HW_ISP;
+	else if (strcmp(token, CAM_COMMON_ICP_NODE) == 0)
+		*hw_id = CAM_COMMON_EVT_INJECT_HW_ICP;
+	else if (strcmp(token, CAM_COMMON_JPEG_NODE) == 0)
+		*hw_id = CAM_COMMON_EVT_INJECT_HW_JPEG;
+	else {
+		CAM_ERR(CAM_UTIL, "Invalid camera hardware [ %s ]", token);
 		return -EINVAL;
+	}
 
-	if (list_empty(&g_err_inject_info.active_err_ctx_list)) {
-		CAM_ERR(CAM_UTIL, "list is empty");
+	return 0;
+}
+
+static inline int cam_common_evt_inject_get_str_id_type(uint8_t *id_type, char *token)
+{
+	if (!strcmp(token, CAM_COMMON_EVT_INJECT_BUFFER_ERROR))
+		*id_type = CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE;
+	else if (!strcmp(token, CAM_COMMON_EVT_INJECT_NOTIFY_EVENT))
+		*id_type = CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE;
+	else {
+		CAM_ERR(CAM_UTIL, "Invalid string id: %s", token);
 		return -EINVAL;
 	}
-	list_for_each_safe(pos, pos_next, &g_err_inject_info.active_err_ctx_list) {
-		err_param = list_entry(pos, struct cam_err_inject_param, list);
-		if (err_param->dev_hdl == dev_hdl) {
-			CAM_INFO(CAM_UTIL, "entry deleted for %llu dev hdl", dev_hdl);
-			list_del(pos);
-			kfree(err_param);
+
+	return 0;
+}
+
+static int cam_common_evt_inject_parse_buffer_error_evt_params(
+	struct cam_common_inject_evt_param *inject_params,
+	uint32_t param_counter, char *token)
+{
+	struct cam_hw_inject_buffer_error_param *buf_err_params =
+		&inject_params->evt_params.u.buf_err_evt;
+	int rc = 0;
+
+	switch (param_counter) {
+	case SYNC_ERROR_CAUSE:
+		if (kstrtou32(token, 0, &buf_err_params->sync_error)) {
+			CAM_ERR(CAM_UTIL, "Invalid event type %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	default:
+		CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_common_evt_inject_parse_node_evt_params(
+	struct cam_common_inject_evt_param *inject_params,
+	uint32_t param_counter, char *token)
+{
+	struct cam_hw_inject_node_evt_param *node_params =
+		&inject_params->evt_params.u.evt_notify.u.node_evt_params;
+	int rc = 0;
+
+	switch (param_counter) {
+	case EVENT_TYPE:
+		if (kstrtou32(token, 0, &node_params->event_type)) {
+			CAM_ERR(CAM_UTIL, "Invalid event type %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	case EVENT_CAUSE:
+		if (kstrtou32(token, 0, &node_params->event_cause)) {
+			CAM_ERR(CAM_UTIL, "Invalid event cause %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	default:
+		CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_common_evt_inject_parse_pf_params(
+	struct cam_common_inject_evt_param *inject_params,
+	uint32_t param_counter, char *token)
+{
+	struct cam_hw_inject_pf_evt_param *pf_params =
+		&inject_params->evt_params.u.evt_notify.u.pf_evt_params;
+	int rc = 0;
+
+	switch (param_counter) {
+	case PF_PARAM_CTX_FOUND:
+		if (kstrtobool(token, &pf_params->ctx_found)) {
+			CAM_ERR(CAM_UTIL, "Invalid context found value %s", token);
+			rc = -EINVAL;
 		}
+		break;
+	default:
+		CAM_ERR(CAM_UTIL, "Invalid extra parameters %s", token);
+		rc = -EINVAL;
 	}
+
 	return rc;
 }
 
-static int cam_err_inject_set(const char *kmessage,
+static int cam_common_evt_inject_parse_err_evt_params(
+	struct cam_common_inject_evt_param *inject_params,
+	uint32_t param_counter, char *token)
+{
+	struct cam_hw_inject_err_evt_param *err_params =
+		&inject_params->evt_params.u.evt_notify.u.err_evt_params;
+	int rc = 0;
+
+	switch (param_counter) {
+	case ERR_PARAM_ERR_TYPE:
+		if (kstrtou32(token, 0, &err_params->err_type)) {
+			CAM_ERR(CAM_UTIL, "Invalid error type %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	case ERR_PARAM_ERR_CODE:
+		if (kstrtou32(token, 0, &err_params->err_code)) {
+			CAM_ERR(CAM_UTIL, "Invalid error code %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	default:
+		CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_common_evt_inject_parse_event_notify(
+	struct cam_common_inject_evt_param *inject_params,
+	uint32_t param_counter, char *token)
+{
+	int rc = 0;
+
+	switch (param_counter) {
+	case EVT_NOTIFY_TYPE:
+		if (kstrtou32(token, 0,
+			&inject_params->evt_params.u.evt_notify.evt_notify_type)) {
+			CAM_ERR(CAM_UTIL, "Invalid Event notify type %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	default:
+		CAM_ERR(CAM_UTIL, "Invalid extra parameters: %s", token);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_common_evt_inject_parse_common_params(
+	struct cam_common_inject_evt_param *inject_params,
+	uint32_t param_counter, char *token)
+{
+	int rc = 0;
+	struct cam_hw_inject_evt_param *evt_param = &inject_params->evt_params;
+
+	switch (param_counter) {
+	case STRING_ID:
+		rc = cam_common_evt_inject_get_str_id_type(&evt_param->inject_id, token);
+		break;
+	case HW_NAME:
+		rc = cam_common_evt_inject_get_hw_id(&inject_params->hw_id, token);
+		break;
+	case DEV_HDL:
+		if (kstrtos32(token, 0, &inject_params->dev_hdl)) {
+			CAM_ERR(CAM_UTIL, "Invalid device handle %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	case REQ_ID:
+		if (kstrtou64(token, 0, &evt_param->req_id)) {
+			CAM_ERR(CAM_UTIL, "Invalid request id %s", token);
+			rc = -EINVAL;
+		}
+		break;
+	default:
+		 CAM_ERR(CAM_UTIL, "Invalid extra parameter: %s", token);
+		 rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_common_evt_inject_generic_command_parser(
+	struct cam_common_inject_evt_param *inject_params,
+	char **msg, uint32_t max_params, cam_common_evt_inject_cmd_parse_handler cmd_parse_cb)
+{
+	char *token = NULL;
+	int rc = 0, param_counter = 0;
+
+	token = strsep(msg, ":");
+	while (token != NULL) {
+		rc = cmd_parse_cb(inject_params, param_counter, token);
+		if (rc) {
+			CAM_ERR(CAM_UTIL, "Parsed Command failed rc: %d", rc);
+			return rc;
+		}
+
+		param_counter++;
+		if (param_counter == max_params)
+			break;
+		token = strsep(msg, ":");
+	}
+
+	if (param_counter < max_params) {
+		CAM_ERR(CAM_UTIL,
+			"Insufficient parameters passed for total parameters: %u",
+			param_counter);
+		return -EINVAL;
+	}
+
+	return rc;
+}
+
+static int cam_common_evt_inject_set(const char *kmessage,
 	const struct kernel_param *kp)
 {
-	int     rc                                         = 0;
-	char    tmp_buff[CAM_COMMON_ERR_INJECT_BUFFER_LEN] = {'\0'};
-	char    *token_start, *token_end;
-	struct  cam_err_inject_param *err_params           = NULL;
-	uint8_t param_counter                              = 0;
-
-	err_params = kzalloc(sizeof(struct cam_err_inject_param), GFP_KERNEL);
-	if (!err_params) {
+	struct   cam_common_inject_evt_param *inject_params   = NULL;
+	struct   cam_hw_inject_evt_param *hw_evt_params       = NULL;
+	cam_common_evt_inject_cmd_parse_handler parse_handler = NULL;
+	int      rc                                           = 0;
+	char     tmp_buff[CAM_COMMON_EVT_INJECT_BUFFER_LEN];
+	char    *msg                                          = NULL;
+	uint32_t param_output                                 = 0;
+
+	inject_params = kzalloc(sizeof(struct cam_common_inject_evt_param), GFP_KERNEL);
+	if (!inject_params) {
 		CAM_ERR(CAM_UTIL, "no free memory");
 		return -ENOMEM;
 	}
 
-	memset(tmp_buff, 0, CAM_COMMON_ERR_INJECT_BUFFER_LEN);
-	rc = strscpy(tmp_buff, kmessage, CAM_COMMON_ERR_INJECT_BUFFER_LEN);
+	rc = strscpy(tmp_buff, kmessage, CAM_COMMON_EVT_INJECT_BUFFER_LEN);
 	if (rc == -E2BIG)
 		goto free;
 
-	token_start = tmp_buff;
-	token_end   = tmp_buff;
-
-	CAM_INFO(CAM_UTIL, "parsing input param for cam_err_inject: %s", tmp_buff);
-	while (token_start != NULL) {
-		strsep(&token_end, ":");
-		switch (param_counter) {
-		case HW_NAME:
-			if (strcmp(token_start, CAM_COMMON_IFE_NODE) == 0)
-				err_params->hw_id = CAM_COMMON_ERR_INJECT_HW_ISP;
-			else if (strcmp(token_start, CAM_COMMON_ICP_NODE) == 0)
-				err_params->hw_id = CAM_COMMON_ERR_INJECT_HW_ICP;
-			else if (strcmp(token_start, CAM_COMMON_JPEG_NODE) == 0)
-				err_params->hw_id = CAM_COMMON_ERR_INJECT_HW_JPEG;
-			else {
-				CAM_ERR(CAM_UTIL, "invalid camera hardware [ %s ]", token_start);
-					goto free;
-			}
-			break;
-		case REQ_ID:
-			if (kstrtou64(token_start, 0, &(err_params->req_id)))
-				goto free;
-			break;
-		case ERR_TYPE:
-			if (kstrtou32(token_start, 0, &(err_params->err_type)))
-				goto free;
+	CAM_INFO(CAM_UTIL, "parsing input param for cam event injection: %s", tmp_buff);
+
+	msg = tmp_buff;
+	hw_evt_params = &inject_params->evt_params;
+
+	rc = cam_common_evt_inject_generic_command_parser(inject_params, &msg,
+		COMMON_PARAM_MAX, cam_common_evt_inject_parse_common_params);
+	if (rc) {
+		CAM_ERR(CAM_UTIL, "Fail to parse common params %d", rc);
+		goto free;
+	}
+
+	switch (hw_evt_params->inject_id) {
+	case CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE:
+		rc = cam_common_evt_inject_generic_command_parser(inject_params, &msg,
+			EVT_NOTIFY_PARAM_MAX, cam_common_evt_inject_parse_event_notify);
+		if (rc) {
+			CAM_ERR(CAM_UTIL, "Fail to parse event notify type param %d", rc);
+			goto free;
+		}
+
+		switch (hw_evt_params->u.evt_notify.evt_notify_type) {
+		case V4L_EVENT_CAM_REQ_MGR_ERROR:
+			parse_handler = cam_common_evt_inject_parse_err_evt_params;
+			param_output = ERR_PARAM_MAX;
 			break;
-		case ERR_CODE:
-			if (kstrtou32(token_start, 0, &(err_params->err_code)))
-				goto free;
+		case V4L_EVENT_CAM_REQ_MGR_NODE_EVENT:
+			parse_handler = cam_common_evt_inject_parse_node_evt_params;
+			param_output = NODE_PARAM_MAX;
 			break;
-		case DEV_HDL:
-			if (kstrtou64(token_start, 0, &(err_params->dev_hdl)))
-				goto free;
+		case V4L_EVENT_CAM_REQ_MGR_PF_ERROR:
+			parse_handler = cam_common_evt_inject_parse_pf_params;
+			param_output = PF_PARAM_MAX;
 			break;
 		default:
-			CAM_ERR(CAM_UTIL, "Insuffiecient parameter count [%d] ", param_counter);
+			CAM_ERR(CAM_UTIL, "Invalid event notification type: %u",
+				hw_evt_params->u.evt_notify.evt_notify_type);
 			goto free;
 		}
-
-		param_counter++;
-		token_start = token_end;
+		break;
+	case CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE:
+		parse_handler = cam_common_evt_inject_parse_buffer_error_evt_params;
+		param_output = BUFFER_ERROR_PARAM_MAX;
+		break;
+	default:
+		CAM_ERR(CAM_UTIL, "Invalid Injection id: %u", hw_evt_params->inject_id);
 	}
 
-	if (param_counter < CAM_COMMON_ERR_INJECT_PARAM_NUM) {
-		CAM_ERR(CAM_UTIL, "Insuffiecient parameter count [%d]", param_counter);
+	rc = cam_common_evt_inject_generic_command_parser(inject_params, &msg,
+		param_output, parse_handler);
+	if (rc) {
+		CAM_ERR(CAM_UTIL, "Command Parsed failed with Inject id: %u rc: %d",
+			hw_evt_params->inject_id, rc);
 		goto free;
 	}
 
-	CAM_INFO(CAM_UTIL, "parsed params: req_id: %llu err_type: %u, err_code: %u dev_hdl: %llu",
-		err_params->req_id, err_params->err_type, err_params->err_code,
-		err_params->dev_hdl);
-
-	if (g_err_inject_info.err_inject_cb[err_params->hw_id]) {
-		rc = g_err_inject_info.err_inject_cb[err_params->hw_id](err_params);
+	if (g_inject_evt_info.evt_inject_cb[inject_params->hw_id]) {
+		rc = g_inject_evt_info.evt_inject_cb[inject_params->hw_id](inject_params);
 		if (rc)
 			goto free;
-		else {
-			if (!g_err_inject_info.is_list_initialised) {
-				INIT_LIST_HEAD(&g_err_inject_info.active_err_ctx_list);
-				g_err_inject_info.is_list_initialised = true;
-			}
-
-			list_add(&err_params->list, &g_err_inject_info.active_err_ctx_list);
-		}
 	} else {
-		CAM_ERR(CAM_UTIL, "Handler for HW_id [%d] not registered", err_params->hw_id);
+		CAM_ERR(CAM_UTIL, "Handler for HW_id [%hhu] not registered", inject_params->hw_id);
 		goto free;
 	}
 
-	if (rc)
-		CAM_ERR(CAM_UTIL, "No Dev_hdl found: [%d]", err_params->dev_hdl);
+	if (!g_inject_evt_info.is_list_initialised) {
+		INIT_LIST_HEAD(&g_inject_evt_info.active_evt_ctx_list);
+		g_inject_evt_info.is_list_initialised = true;
+	}
+
+	list_add(&inject_params->list, &g_inject_evt_info.active_evt_ctx_list);
 
 	return rc;
+
 free:
-	kfree(err_params);
-	return -EINVAL;
+	kfree(inject_params);
+	return rc;
 }
 
-static int cam_err_inject_get(char *buffer,
+static int cam_common_evt_inject_get(char *buffer,
 	const struct kernel_param *kp)
 {
-	uint8_t hw_name[10];
-	uint16_t buff_max_size = CAM_COMMON_ERR_MODULE_PARAM_MAX_LENGTH;
-	struct cam_err_inject_param *err_param;
-	int ret = 0;
+	uint8_t hw_name[16], string_id[16];
+	uint16_t buff_max_size = CAM_COMMON_EVT_INJECT_MODULE_PARAM_MAX_LENGTH;
+	struct cam_common_inject_evt_param *inject_params = NULL;
+	struct cam_hw_inject_evt_param *evt_params = NULL;
+	uint32_t  ret = 0;
 
-	if (!g_err_inject_info.is_list_initialised)
+	if (!g_inject_evt_info.is_list_initialised)
 		return scnprintf(buffer, buff_max_size, "uninitialised");
 
-	else if (!list_empty(&g_err_inject_info.active_err_ctx_list)) {
-		list_for_each_entry(err_param, &g_err_inject_info.active_err_ctx_list, list) {
-			switch (err_param->hw_id) {
-			case CAM_COMMON_ERR_INJECT_HW_ISP:
-				strscpy(hw_name, CAM_COMMON_IFE_NODE, 10);
+	if (list_empty(&g_inject_evt_info.active_evt_ctx_list))
+		return scnprintf(buffer, buff_max_size, "Active err inject list is empty");
+
+	list_for_each_entry(inject_params, &g_inject_evt_info.active_evt_ctx_list, list) {
+		evt_params = &inject_params->evt_params;
+
+		switch (inject_params->hw_id) {
+		case CAM_COMMON_EVT_INJECT_HW_ISP:
+			strscpy(hw_name, CAM_COMMON_IFE_NODE, sizeof(hw_name));
+			break;
+		case CAM_COMMON_EVT_INJECT_HW_ICP:
+			strscpy(hw_name, CAM_COMMON_ICP_NODE, sizeof(hw_name));
+			break;
+		case CAM_COMMON_EVT_INJECT_HW_JPEG:
+			strscpy(hw_name, CAM_COMMON_JPEG_NODE, sizeof(hw_name));
+			break;
+		default:
+			ret += scnprintf(buffer+ret, buff_max_size, "Undefined HW id\n");
+			goto undefined_param;
+		}
+
+		switch (evt_params->inject_id) {
+		case CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE:
+			strscpy(string_id, CAM_COMMON_EVT_INJECT_BUFFER_ERROR, sizeof(string_id));
+			break;
+		case CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE:
+			strscpy(string_id, CAM_COMMON_EVT_INJECT_NOTIFY_EVENT, sizeof(string_id));
+			break;
+		default:
+			ret += scnprintf(buffer+ret, buff_max_size, "Undefined string id\n");
+			goto undefined_param;
+		}
+
+		ret += scnprintf(buffer+ret, buff_max_size,
+			"string_id: %s hw_name: %s dev_hdl: %d req_id: %llu ",
+			string_id, hw_name,
+			inject_params->dev_hdl, evt_params->req_id);
+
+		if (buff_max_size > ret) {
+			buff_max_size -= ret;
+		} else {
+			CAM_WARN(CAM_UTIL, "out buff max limit reached");
+			break;
+		}
+
+		if (evt_params->inject_id ==
+			CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE) {
+			ret += scnprintf(buffer+ret, buff_max_size,
+				"sync_error: %u\n", evt_params->u.buf_err_evt.sync_error);
+		} else {
+			switch (evt_params->u.evt_notify.evt_notify_type) {
+			case V4L_EVENT_CAM_REQ_MGR_ERROR: {
+				struct cam_hw_inject_err_evt_param *err_evt_params =
+					&evt_params->u.evt_notify.u.err_evt_params;
+				ret += scnprintf(buffer+ret, buff_max_size,
+					"Error event: error type: %u error code: %u\n",
+					err_evt_params->err_type, err_evt_params->err_code);
 				break;
-			case CAM_COMMON_ERR_INJECT_HW_ICP:
-				strscpy(hw_name, CAM_COMMON_ICP_NODE, 10);
+			}
+			case V4L_EVENT_CAM_REQ_MGR_NODE_EVENT: {
+				struct cam_hw_inject_node_evt_param *node_evt_params =
+					&evt_params->u.evt_notify.u.node_evt_params;
+				ret += scnprintf(buffer+ret, buff_max_size,
+					"Node event: event type: %u event cause: %u\n",
+					node_evt_params->event_type, node_evt_params->event_cause);
 				break;
-			case CAM_COMMON_ERR_INJECT_HW_JPEG:
-				strscpy(hw_name, CAM_COMMON_JPEG_NODE, 10);
+			}
+			case V4L_EVENT_CAM_REQ_MGR_PF_ERROR: {
+				struct cam_hw_inject_pf_evt_param *pf_evt_params =
+					&evt_params->u.evt_notify.u.pf_evt_params;
+				ret += scnprintf(buffer+ret, buff_max_size,
+					"PF event: ctx found %hhu\n",
+					pf_evt_params->ctx_found);
 				break;
+			}
 			default:
-				strscpy(hw_name, "undef", 10);
+				ret += scnprintf(buffer+ret, buff_max_size,
+					"Undefined notification event\n");
 			}
-			ret += scnprintf(buffer+ret, buff_max_size,
-				"hw_name: %s req_id: %u err_type: %u err_code: %u dev_hdl: %d\n",
-				hw_name, err_param->req_id, err_param->err_type,
-				err_param->err_code, err_param->dev_hdl);
+		}
 
-			CAM_DBG(CAM_UTIL, "output buffer: %s", buffer);
+undefined_param:
+		CAM_DBG(CAM_UTIL, "output buffer: %s", buffer);
 
-			if (ret < buff_max_size) {
-				buff_max_size = buff_max_size - ret;
-			} else {
-				CAM_WARN(CAM_UTIL, "out buff max limit reached");
-				break;
-			}
+		if (buff_max_size > ret) {
+			buff_max_size -= ret;
+		} else {
+			CAM_WARN(CAM_UTIL, "out buff max limit reached");
+			break;
 		}
-		return ret;
 	}
 
-	return scnprintf(buffer, buff_max_size, "uninitialised");
+	return ret;
 }
 
-static const struct kernel_param_ops cam_error_inject_ops = {
-	.set = cam_err_inject_set,
-	.get = cam_err_inject_get
+static const struct kernel_param_ops cam_common_evt_inject = {
+	.set = cam_common_evt_inject_set,
+	.get = cam_common_evt_inject_get
 };
 
-module_param_cb(cam_error_inject, &cam_error_inject_ops, NULL, 0644);
+module_param_cb(cam_event_inject, &cam_common_evt_inject, NULL, 0644);

+ 94 - 43
drivers/cam_utils/cam_common_util.h

@@ -10,6 +10,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 
+#include "cam_hw_mgr_intf.h"
+
 #define CAM_BITS_MASK_SHIFT(x, mask, shift) (((x) & (mask)) >> shift)
 #define CAM_36BIT_INTF_GET_IOVA_BASE(iova) ((iova) >> 8)
 #define CAM_36BIT_INTF_GET_IOVA_OFFSET(iova) ((iova) & 0xff)
@@ -21,12 +23,12 @@
 #define CAM_COMMON_HW_DUMP_TAG_MAX_LEN 64
 #define CAM_MAX_NUM_CCI_PAYLOAD_BYTES     11
 
-#define CAM_COMMON_ERR_MODULE_PARAM_MAX_LENGTH  4096
-#define CAM_COMMON_ERR_INJECT_BUFFER_LEN  200
-#define CAM_COMMON_ERR_INJECT_DEV_MAX     5
-#define CAM_COMMON_ERR_INJECT_PARAM_NUM   5
-#define CAM_COMMON_IFE_NODE "IFE"
-#define CAM_COMMON_ICP_NODE "IPE"
+#define CAM_COMMON_EVT_INJECT_MODULE_PARAM_MAX_LENGTH 4096
+#define CAM_COMMON_EVT_INJECT_BUFFER_LEN              200
+#define CAM_COMMON_EVT_INJECT_BUFFER_ERROR "Buffer_Error"
+#define CAM_COMMON_EVT_INJECT_NOTIFY_EVENT "Notify_Event"
+#define CAM_COMMON_IFE_NODE  "IFE"
+#define CAM_COMMON_ICP_NODE  "IPE"
 #define CAM_COMMON_JPEG_NODE "JPEG"
 
 #define CAM_COMMON_NS_PER_MS              1000000ULL
@@ -110,49 +112,91 @@ struct cam_common_mini_dump_data {
 };
 
 
-typedef int (*cam_common_err_inject_cb) (void *err_param);
-int cam_common_release_err_params(uint64_t dev_hdl);
+typedef int (*cam_common_evt_inject_cb) (void *inject_args);
+
+enum cam_common_evt_inject_str_id_type {
+	CAM_COMMON_EVT_INJECT_BUFFER_ERROR_TYPE,
+	CAM_COMMON_EVT_INJECT_NOTIFY_EVENT_TYPE
+};
 
-enum cam_common_err_inject_hw_id {
-	CAM_COMMON_ERR_INJECT_HW_ISP,
-	CAM_COMMON_ERR_INJECT_HW_ICP,
-	CAM_COMMON_ERR_INJECT_HW_JPEG,
-	CAM_COMMON_ERR_INJECT_HW_MAX
+enum cam_common_evt_inject_hw_id {
+	CAM_COMMON_EVT_INJECT_HW_ISP,
+	CAM_COMMON_EVT_INJECT_HW_ICP,
+	CAM_COMMON_EVT_INJECT_HW_JPEG,
+	CAM_COMMON_EVT_INJECT_HW_MAX
 };
 
-enum cam_common_err_inject_input_param_pos {
-	HW_NAME = 0,
+enum cam_common_evt_inject_common_param_pos {
+	STRING_ID,
+	HW_NAME,
+	DEV_HDL,
 	REQ_ID,
-	ERR_TYPE,
-	ERR_CODE,
-	DEV_HDL
+	COMMON_PARAM_MAX
+};
+
+enum cam_common_evt_inject_notify_event_pos {
+	EVT_NOTIFY_TYPE,
+	EVT_NOTIFY_PARAM_MAX
+};
+
+enum cam_evt_inject_buffer_error_event {
+	SYNC_ERROR_CAUSE,
+	BUFFER_ERROR_PARAM_MAX
+};
+
+enum cam_evt_inject_error_param_pos {
+	ERR_PARAM_ERR_TYPE,
+	ERR_PARAM_ERR_CODE,
+	ERR_PARAM_MAX
+};
+
+enum cam_evt_inject_node_param_pos {
+	EVENT_TYPE,
+	EVENT_CAUSE,
+	NODE_PARAM_MAX,
+};
+
+enum cam_evt_inject_pf_params_pos {
+	PF_PARAM_CTX_FOUND,
+	PF_PARAM_MAX
 };
 
 /**
- * @req_id  : req id for err to be injected
- * @dev_hdl : dev_hdl for the context
- * @err_type: error type for error request
- * @err_code: error code for error request
- * @hw_id   : hw id representing hw nodes of type cam_common_err_inject_hw_id
+ * struct cam_common_evt_inject_data
+ * @buf_done_data: buf done data
+ * @evt_params   : event params for the injected event
  */
-struct cam_err_inject_param {
-	struct list_head  list;
-	uint64_t          req_id;
-	uint64_t          dev_hdl;
-	uint32_t          err_type;
-	uint32_t          err_code;
-	uint8_t           hw_id;
+struct cam_common_evt_inject_data {
+	void                           *buf_done_data;
+	struct cam_hw_inject_evt_param *evt_params;
 };
+
+typedef int (*cam_common_evt_inject_ops) (void *cam_ctx,
+	struct cam_common_evt_inject_data *inject_evt);
+
 /**
- * struct cam_common_err_inject_info
- * @err_inject_cb      : address of callback
- * @active_err_ctx_list: list containing active err inject requests
+ * struct cam_common_inject_evt_param
+ * @evt_params : injection event params
+ * @dev_hdl    : device handle to match with ctx's dev_hdl
+ * @hw_id      : hw to be injected with the event
+ */
+struct cam_common_inject_evt_param {
+	struct list_head list;
+	struct cam_hw_inject_evt_param evt_params;
+	int32_t dev_hdl;
+	uint8_t hw_id;
+};
+
+/**
+ * struct cam_common_inject_evt_info
+ * @evt_inject_cb      : address of callback
+ * @active_err_ctx_list: list containing active evt inject requests
  * @num_hw_registered  : number of callbacks registered
- * @is_list_initialised: bool to check init for err_inject list
+ * @is_list_initialised: bool to check init for evt_inject list
  */
-struct cam_common_err_inject_info {
-	cam_common_err_inject_cb    err_inject_cb[CAM_COMMON_ERR_INJECT_HW_MAX];
-	struct list_head            active_err_ctx_list;
+struct cam_common_inject_evt_info {
+	cam_common_evt_inject_cb    evt_inject_cb[CAM_COMMON_EVT_INJECT_HW_MAX];
+	struct list_head            active_evt_ctx_list;
 	uint8_t                     num_hw_registered;
 	bool                        is_list_initialised;
 };
@@ -189,6 +233,13 @@ struct cam_common_hw_dump_header {
 	uint32_t  word_size;
 };
 
+/**
+ * @brief                 release all event inject params in the g_inject_evt_info
+ *                        for a specific dev_hdl
+ * @dev_hdl:              device handle to which the evt inject params belong to
+ */
+void cam_common_release_evt_params(int32_t dev_hdl);
+
 /**
  * cam_common_util_get_string_index()
  *
@@ -338,17 +389,17 @@ int cam_common_user_dump_helper(
 	...);
 
 /**
- * cam_common_register_err_inject_cb()
+ * cam_common_register_evt_inject_cb()
  *
- * @brief                  common interface to register error inject cb
+ * @brief                  common interface to register evt inject cb
  *
- * @err_inject_cb:         Pointer to err_inject_cb
+ * @evt_inject_cb:         Pointer to evt_inject_cb
  * @hw_id:                 HW id of the HW driver registering
  *
  * @return:                0 if success in register non-zero if failes
  */
-int cam_common_register_err_inject_cb(
-	cam_common_err_inject_cb err_inject_cb,
-	enum cam_common_err_inject_hw_id hw_id);
+int cam_common_register_evt_inject_cb(
+	cam_common_evt_inject_cb evt_inject_cb,
+	enum cam_common_evt_inject_hw_id hw_id);
 
 #endif /* _CAM_COMMON_UTIL_H_ */