|
@@ -49,6 +49,11 @@ static const char *__cam_isp_hw_evt_val_to_type(
|
|
static const char *__cam_isp_ctx_substate_val_to_type(
|
|
static const char *__cam_isp_ctx_substate_val_to_type(
|
|
enum cam_isp_ctx_activated_substate type);
|
|
enum cam_isp_ctx_activated_substate type);
|
|
|
|
|
|
|
|
+static int __cam_isp_ctx_check_deferred_buf_done(
|
|
|
|
+ struct cam_isp_context *ctx_isp,
|
|
|
|
+ struct cam_isp_hw_done_event_data *done,
|
|
|
|
+ uint32_t bubble_state);
|
|
|
|
+
|
|
static const char *__cam_isp_evt_val_to_type(
|
|
static const char *__cam_isp_evt_val_to_type(
|
|
uint32_t evt_id)
|
|
uint32_t evt_id)
|
|
{
|
|
{
|
|
@@ -1848,6 +1853,7 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
struct cam_context *ctx = ctx_isp->base;
|
|
struct cam_context *ctx = ctx_isp->base;
|
|
const char *handle_type;
|
|
const char *handle_type;
|
|
uint32_t cmp_addr = 0;
|
|
uint32_t cmp_addr = 0;
|
|
|
|
+ struct cam_isp_hw_done_event_data unhandled_done = {0};
|
|
|
|
|
|
trace_cam_buf_done("ISP", ctx, req);
|
|
trace_cam_buf_done("ISP", ctx, req);
|
|
|
|
|
|
@@ -1863,6 +1869,8 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ unhandled_done.timestamp = done->timestamp;
|
|
|
|
+
|
|
for (i = 0; i < done->num_handles; i++) {
|
|
for (i = 0; i < done->num_handles; i++) {
|
|
for (j = 0; j < req_isp->num_fence_map_out; j++) {
|
|
for (j = 0; j < req_isp->num_fence_map_out; j++) {
|
|
cmp_addr = cam_smmu_is_expanded_memory() ? CAM_36BIT_INTF_GET_IOVA_BASE(
|
|
cmp_addr = cam_smmu_is_expanded_memory() ? CAM_36BIT_INTF_GET_IOVA_BASE(
|
|
@@ -1888,6 +1896,11 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
__cam_isp_resource_handle_id_to_type(
|
|
__cam_isp_resource_handle_id_to_type(
|
|
ctx_isp->isp_device_type, done->resource_handle[i]),
|
|
ctx_isp->isp_device_type, done->resource_handle[i]),
|
|
req->request_id);
|
|
req->request_id);
|
|
|
|
+ unhandled_done.resource_handle[unhandled_done.num_handles] =
|
|
|
|
+ done->resource_handle[i];
|
|
|
|
+ unhandled_done.last_consumed_addr[unhandled_done.num_handles] =
|
|
|
|
+ done->last_consumed_addr[i];
|
|
|
|
+ unhandled_done.num_handles++;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2037,6 +2050,10 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
req->request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS);
|
|
req->request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if ((unhandled_done.num_handles > 0) && (!defer_buf_done))
|
|
|
|
+ __cam_isp_ctx_check_deferred_buf_done(
|
|
|
|
+ ctx_isp, &unhandled_done, bubble_state);
|
|
|
|
+
|
|
if (req_isp->num_acked > req_isp->num_fence_map_out) {
|
|
if (req_isp->num_acked > req_isp->num_fence_map_out) {
|
|
/* Should not happen */
|
|
/* Should not happen */
|
|
CAM_ERR(CAM_ISP,
|
|
CAM_ERR(CAM_ISP,
|
|
@@ -2154,93 +2171,106 @@ static void __cam_isp_ctx_buf_done_match_req(
|
|
"irq_delay_detected %d", *irq_delay_detected);
|
|
"irq_delay_detected %d", *irq_delay_detected);
|
|
}
|
|
}
|
|
|
|
|
|
-static int __cam_isp_ctx_handle_buf_done_verify_addr(
|
|
|
|
|
|
+static int __cam_isp_ctx_check_deferred_buf_done(
|
|
struct cam_isp_context *ctx_isp,
|
|
struct cam_isp_context *ctx_isp,
|
|
struct cam_isp_hw_done_event_data *done,
|
|
struct cam_isp_hw_done_event_data *done,
|
|
uint32_t bubble_state)
|
|
uint32_t bubble_state)
|
|
{
|
|
{
|
|
int rc = 0;
|
|
int rc = 0;
|
|
- bool irq_delay_detected = false;
|
|
|
|
struct cam_ctx_request *req;
|
|
struct cam_ctx_request *req;
|
|
- struct cam_ctx_request *next_req = NULL;
|
|
|
|
struct cam_context *ctx = ctx_isp->base;
|
|
struct cam_context *ctx = ctx_isp->base;
|
|
struct cam_isp_ctx_req *req_isp;
|
|
struct cam_isp_ctx_req *req_isp;
|
|
bool req_in_pending_wait_list = false;
|
|
bool req_in_pending_wait_list = false;
|
|
|
|
|
|
- if (list_empty(&ctx->active_req_list)) {
|
|
|
|
-
|
|
|
|
- if (!list_empty(&ctx->wait_req_list)) {
|
|
|
|
- req = list_first_entry(&ctx->wait_req_list,
|
|
|
|
- struct cam_ctx_request, list);
|
|
|
|
|
|
+ if (!list_empty(&ctx->wait_req_list)) {
|
|
|
|
+ req = list_first_entry(&ctx->wait_req_list,
|
|
|
|
+ struct cam_ctx_request, list);
|
|
|
|
|
|
- req_in_pending_wait_list = true;
|
|
|
|
- if (ctx_isp->last_applied_req_id !=
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id) {
|
|
|
|
- CAM_WARN(CAM_ISP,
|
|
|
|
- "Buf done with no active request but with req in wait list, req %llu last apply id:%lld last err id:%lld",
|
|
|
|
- req->request_id,
|
|
|
|
- ctx_isp->last_applied_req_id,
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id);
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id =
|
|
|
|
- ctx_isp->last_applied_req_id;
|
|
|
|
- }
|
|
|
|
|
|
+ req_in_pending_wait_list = true;
|
|
|
|
+ if (ctx_isp->last_applied_req_id !=
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id) {
|
|
|
|
+ CAM_INFO(CAM_ISP,
|
|
|
|
+ "Buf done with no active request but with req in wait list, req %llu last apply id:%lld last err id:%lld",
|
|
|
|
+ req->request_id,
|
|
|
|
+ ctx_isp->last_applied_req_id,
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id);
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id =
|
|
|
|
+ ctx_isp->last_applied_req_id;
|
|
|
|
+ }
|
|
|
|
|
|
- req_isp = (struct cam_isp_ctx_req *) req->req_priv;
|
|
|
|
|
|
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
|
|
|
|
|
|
- /*
|
|
|
|
- * Verify consumed address for this request to make sure
|
|
|
|
- * we are handling the buf_done for the correct
|
|
|
|
- * buffer. Also defer actual buf_done handling, i.e
|
|
|
|
- * do not signal the fence as this request may go into
|
|
|
|
- * Bubble state eventully.
|
|
|
|
- */
|
|
|
|
- rc =
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Verify consumed address for this request to make sure
|
|
|
|
+ * we are handling the buf_done for the correct
|
|
|
|
+ * buffer. Also defer actual buf_done handling, i.e
|
|
|
|
+ * do not signal the fence as this request may go into
|
|
|
|
+ * Bubble state eventully.
|
|
|
|
+ */
|
|
|
|
+ rc =
|
|
__cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
__cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
ctx_isp, req, done, bubble_state, true, true);
|
|
ctx_isp, req, done, bubble_state, true, true);
|
|
- } else if (!list_empty(&ctx->pending_req_list)) {
|
|
|
|
- /*
|
|
|
|
- * We saw the case that the hw config is blocked due to
|
|
|
|
- * some reason, the we get the reg upd and buf done before
|
|
|
|
- * the req is added to wait req list.
|
|
|
|
- */
|
|
|
|
- req = list_first_entry(&ctx->pending_req_list,
|
|
|
|
- struct cam_ctx_request, list);
|
|
|
|
|
|
+ } else if (!list_empty(&ctx->pending_req_list)) {
|
|
|
|
+ /*
|
|
|
|
+ * We saw the case that the hw config is blocked due to
|
|
|
|
+ * some reason, the we get the reg upd and buf done before
|
|
|
|
+ * the req is added to wait req list.
|
|
|
|
+ */
|
|
|
|
+ req = list_first_entry(&ctx->pending_req_list,
|
|
|
|
+ struct cam_ctx_request, list);
|
|
|
|
|
|
- req_in_pending_wait_list = true;
|
|
|
|
- if (ctx_isp->last_applied_req_id !=
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id) {
|
|
|
|
- CAM_WARN(CAM_ISP,
|
|
|
|
- "Buf done with no active request but with req in pending list, req %llu last apply id:%lld last err id:%lld",
|
|
|
|
- req->request_id,
|
|
|
|
- ctx_isp->last_applied_req_id,
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id);
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id =
|
|
|
|
- ctx_isp->last_applied_req_id;
|
|
|
|
- }
|
|
|
|
|
|
+ req_in_pending_wait_list = true;
|
|
|
|
+ if (ctx_isp->last_applied_req_id !=
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id) {
|
|
|
|
+ CAM_INFO(CAM_ISP,
|
|
|
|
+ "Buf done with no active request but with req in pending list, req %llu last apply id:%lld last err id:%lld",
|
|
|
|
+ req->request_id,
|
|
|
|
+ ctx_isp->last_applied_req_id,
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id);
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id =
|
|
|
|
+ ctx_isp->last_applied_req_id;
|
|
|
|
+ }
|
|
|
|
|
|
- req_isp = (struct cam_isp_ctx_req *) req->req_priv;
|
|
|
|
|
|
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
|
|
|
|
|
|
- /*
|
|
|
|
- * Verify consumed address for this request to make sure
|
|
|
|
- * we are handling the buf_done for the correct
|
|
|
|
- * buffer. Also defer actual buf_done handling, i.e
|
|
|
|
- * do not signal the fence as this request may go into
|
|
|
|
- * Bubble state eventully.
|
|
|
|
- */
|
|
|
|
- rc =
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Verify consumed address for this request to make sure
|
|
|
|
+ * we are handling the buf_done for the correct
|
|
|
|
+ * buffer. Also defer actual buf_done handling, i.e
|
|
|
|
+ * do not signal the fence as this request may go into
|
|
|
|
+ * Bubble state eventully.
|
|
|
|
+ */
|
|
|
|
+ rc =
|
|
__cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
__cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
|
ctx_isp, req, done, bubble_state, true, true);
|
|
ctx_isp, req, done, bubble_state, true, true);
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- if (!req_in_pending_wait_list && (ctx_isp->last_applied_req_id !=
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id)) {
|
|
|
|
- CAM_WARN(CAM_ISP,
|
|
|
|
- "Buf done with no active request bubble_state=%d last_applied_req_id:%lld ",
|
|
|
|
- bubble_state, ctx_isp->last_applied_req_id);
|
|
|
|
- ctx_isp->last_bufdone_err_apply_req_id =
|
|
|
|
- ctx_isp->last_applied_req_id;
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
|
|
+ if (!req_in_pending_wait_list && (ctx_isp->last_applied_req_id !=
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id)) {
|
|
|
|
+ CAM_WARN(CAM_ISP,
|
|
|
|
+ "Buf done with no active request bubble_state=%d last_applied_req_id:%lld ",
|
|
|
|
+ bubble_state, ctx_isp->last_applied_req_id);
|
|
|
|
+ ctx_isp->last_bufdone_err_apply_req_id =
|
|
|
|
+ ctx_isp->last_applied_req_id;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int __cam_isp_ctx_handle_buf_done_verify_addr(
|
|
|
|
+ struct cam_isp_context *ctx_isp,
|
|
|
|
+ struct cam_isp_hw_done_event_data *done,
|
|
|
|
+ uint32_t bubble_state)
|
|
|
|
+{
|
|
|
|
+ int rc = 0;
|
|
|
|
+ bool irq_delay_detected = false;
|
|
|
|
+ struct cam_ctx_request *req;
|
|
|
|
+ struct cam_ctx_request *next_req = NULL;
|
|
|
|
+ struct cam_context *ctx = ctx_isp->base;
|
|
|
|
+
|
|
|
|
+ if (list_empty(&ctx->active_req_list)) {
|
|
|
|
+ return __cam_isp_ctx_check_deferred_buf_done(
|
|
|
|
+ ctx_isp, done, bubble_state);
|
|
}
|
|
}
|
|
|
|
|
|
req = list_first_entry(&ctx->active_req_list,
|
|
req = list_first_entry(&ctx->active_req_list,
|