msm: camera: isp: Add unhandled buf done to deferred list
Some unhandled buf dones belong to next req, we need to add them to deferred buf done list and process it in future. CRs-Fixed: 3197114 Change-Id: I5489cb6faacf2b6c9018b3b660a1df2ee6ac9564 Signed-off-by: Depeng Shao <quic_depengs@quicinc.com>
This commit is contained in:

committed by
Camera Software Integration

szülő
eddb106bb8
commit
61d3d3f5d9
@@ -49,6 +49,11 @@ static const char *__cam_isp_hw_evt_val_to_type(
|
||||
static const char *__cam_isp_ctx_substate_val_to_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(
|
||||
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;
|
||||
const char *handle_type;
|
||||
uint32_t cmp_addr = 0;
|
||||
struct cam_isp_hw_done_event_data unhandled_done = {0};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
unhandled_done.timestamp = done->timestamp;
|
||||
|
||||
for (i = 0; i < done->num_handles; i++) {
|
||||
for (j = 0; j < req_isp->num_fence_map_out; j++) {
|
||||
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(
|
||||
ctx_isp->isp_device_type, done->resource_handle[i]),
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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) {
|
||||
/* Should not happen */
|
||||
CAM_ERR(CAM_ISP,
|
||||
@@ -2154,6 +2171,92 @@ static void __cam_isp_ctx_buf_done_match_req(
|
||||
"irq_delay_detected %d", *irq_delay_detected);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cam_ctx_request *req;
|
||||
struct cam_context *ctx = ctx_isp->base;
|
||||
struct cam_isp_ctx_req *req_isp;
|
||||
bool req_in_pending_wait_list = false;
|
||||
|
||||
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_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;
|
||||
|
||||
/*
|
||||
* 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(
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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(
|
||||
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 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,
|
||||
@@ -2164,83 +2267,10 @@ static int __cam_isp_ctx_handle_buf_done_verify_addr(
|
||||
struct cam_ctx_request *req;
|
||||
struct cam_ctx_request *next_req = NULL;
|
||||
struct cam_context *ctx = ctx_isp->base;
|
||||
struct cam_isp_ctx_req *req_isp;
|
||||
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);
|
||||
|
||||
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_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 =
|
||||
__cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
||||
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);
|
||||
|
||||
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_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 =
|
||||
__cam_isp_ctx_handle_buf_done_for_request_verify_addr(
|
||||
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;
|
||||
return __cam_isp_ctx_check_deferred_buf_done(
|
||||
ctx_isp, done, bubble_state);
|
||||
}
|
||||
|
||||
req = list_first_entry(&ctx->active_req_list,
|
||||
|
Reference in New Issue
Block a user