Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50ab715c authored by Jeyaprakash Soundrapandian's avatar Jeyaprakash Soundrapandian Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: isp: State monitoring in isp for error logging" into dev/msm-4.9-camx

parents 98acf5dc c0cab065
Loading
Loading
Loading
Loading
+170 −23
Original line number Diff line number Diff line
@@ -26,6 +26,97 @@

static const char isp_dev_name[] = "isp";

#define INC_STATE_MONITOR_HEAD(head) \
	(atomic64_add_return(1, head) % \
	CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES)

static void __cam_isp_ctx_update_state_monitor_array(
	struct cam_isp_context *ctx_isp,
	enum cam_isp_state_change_trigger trigger_type,
	uint32_t req_id)
{
	int iterator = 0;

	iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head);
	ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state =
		ctx_isp->substate_activated;
	ctx_isp->cam_isp_ctx_state_monitor[iterator].trigger =
		trigger_type;
	ctx_isp->cam_isp_ctx_state_monitor[iterator].req_id =
		req_id;
	ctx_isp->cam_isp_ctx_state_monitor[iterator].evt_time_stamp =
		jiffies_to_msecs(jiffies);
}

static const char *__cam_isp_ctx_substate_val_to_type(
	uint32_t type)
{
	switch (type) {
	case CAM_ISP_CTX_ACTIVATED_SOF:
		return "SOF";
	case CAM_ISP_CTX_ACTIVATED_APPLIED:
		return "APPLIED";
	case CAM_ISP_CTX_ACTIVATED_EPOCH:
		return "EPOCH";
	case CAM_ISP_CTX_ACTIVATED_BUBBLE:
		return "BUBBLE";
	case CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED:
		return "BUBBLE_APPLIED";
	case CAM_ISP_CTX_ACTIVATED_HALT:
		return "HALT";
	default:
		return "CAM_ISP_CTX_INVALID_STATE";
	}
}

static const char *__cam_isp_hw_evt_val_to_type(
	uint32_t evt_id)
{
	switch (evt_id) {
	case CAM_ISP_STATE_CHANGE_TRIGGER_ERROR:
		return "ERROR";
	case CAM_ISP_STATE_CHANGE_TRIGGER_SOF:
		return "SOF";
	case CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE:
		return "REG_UPDATE";
	case CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH:
		return "EPOCH";
	case CAM_ISP_STATE_CHANGE_TRIGGER_EOF:
		return "EOF";
	case CAM_ISP_STATE_CHANGE_TRIGGER_DONE:
		return "DONE";
	default:
		return "CAM_ISP_EVENT_INVALID";
	}
}

static void __cam_isp_ctx_dump_state_monitor_array(
	struct cam_isp_context *ctx_isp)
{
	int i = 0;
	uint64_t state_head = 0;
	uint64_t index;

	state_head = atomic64_read(&ctx_isp->state_monitor_head);
	CAM_ERR_RATE_LIMIT(CAM_ISP,
		"Dumping state information for preceding requests");

	for (i = CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES - 1; i >= 0;
		i--) {
		index = (((state_head - i) +
			CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) %
			CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES);
		CAM_ERR_RATE_LIMIT(CAM_ISP,
		"time[0x%llx] req_id[%u] state[%s] evt_type[%s]",
		ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp,
		ctx_isp->cam_isp_ctx_state_monitor[index].req_id,
		__cam_isp_ctx_substate_val_to_type(
		ctx_isp->cam_isp_ctx_state_monitor[index].curr_state),
		__cam_isp_hw_evt_val_to_type(
		ctx_isp->cam_isp_ctx_state_monitor[index].trigger));
	}
}

static int __cam_isp_ctx_enqueue_request_in_order(
	struct cam_context *ctx, struct cam_ctx_request *req)
{
@@ -134,46 +225,46 @@ static int __cam_isp_ctx_enqueue_init_request(
	return rc;
}

static const char *__cam_isp_resource_handle_id_to_type
	(uint32_t resource_handle)
static const char *__cam_isp_resource_handle_id_to_type(
	uint32_t resource_handle)
{
	switch (resource_handle) {
	case CAM_ISP_IFE_OUT_RES_FULL:
		return "CAM_ISP_IFE_OUT_RES_FULL";
		return "FULL";
	case CAM_ISP_IFE_OUT_RES_DS4:
		return "CAM_ISP_IFE_OUT_RES_DS4";
		return "DS4";
	case CAM_ISP_IFE_OUT_RES_DS16:
		return "CAM_ISP_IFE_OUT_RES_DS16";
		return "DS16";
	case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
		return "CAM_ISP_IFE_OUT_RES_RAW_DUMP";
		return "RAW_DUMP";
	case CAM_ISP_IFE_OUT_RES_FD:
		return "CAM_ISP_IFE_OUT_RES_FD";
		return "FD";
	case CAM_ISP_IFE_OUT_RES_PDAF:
		return "CAM_ISP_IFE_OUT_RES_PDAF";
		return "PDAF";
	case CAM_ISP_IFE_OUT_RES_RDI_0:
		return "CAM_ISP_IFE_OUT_RES_RDI_0";
		return "RDI_0";
	case CAM_ISP_IFE_OUT_RES_RDI_1:
		return "CAM_ISP_IFE_OUT_RES_RDI_1";
		return "RDI_1";
	case CAM_ISP_IFE_OUT_RES_RDI_2:
		return "CAM_ISP_IFE_OUT_RES_RDI_2";
		return "RDI_2";
	case CAM_ISP_IFE_OUT_RES_RDI_3:
		return "CAM_ISP_IFE_OUT_RES_RDI_3";
		return "RDI_3";
	case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
		return "CAM_ISP_IFE_OUT_RES_STATS_HDR_BE";
		return "STATS_HDR_BE";
	case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
		return "CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST";
		return "STATS_HDR_BHIST";
	case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
		return "CAM_ISP_IFE_OUT_RES_STATS_TL_BG";
		return "STATS_TL_BG";
	case CAM_ISP_IFE_OUT_RES_STATS_BF:
		return "CAM_ISP_IFE_OUT_RES_STATS_BF";
		return "STATS_BF";
	case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
		return "CAM_ISP_IFE_OUT_RES_STATS_AWB_BG";
		return "STATS_AWB_BG";
	case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
		return "CAM_ISP_IFE_OUT_RES_STATS_BHIST";
		return "STATS_BHIST";
	case CAM_ISP_IFE_OUT_RES_STATS_RS:
		return "CAM_ISP_IFE_OUT_RES_STATS_RS";
		return "STATS_RS";
	case CAM_ISP_IFE_OUT_RES_STATS_CS:
		return "CAM_ISP_IFE_OUT_RES_STATS_CS";
		return "STATS_CS";
	default:
		return "CAM_ISP_Invalid_Resource_Type";
	}
@@ -350,6 +441,9 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
	}

end:
	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
		CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
		ctx_isp->base->req_list->request_id);
	return rc;
}

@@ -510,6 +604,11 @@ static int __cam_isp_ctx_sof_in_activated_state(
{
	int rc = 0;
	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
	struct cam_ctx_request *req;
	struct cam_context *ctx = ctx_isp->base;

	req = list_last_entry(&ctx->pending_req_list,
		struct cam_ctx_request, list);

	if (!evt_data) {
		CAM_ERR(CAM_ISP, "in valid sof event data");
@@ -518,6 +617,8 @@ static int __cam_isp_ctx_sof_in_activated_state(

	ctx_isp->frame_id++;
	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
		CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);

@@ -528,11 +629,11 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
	void *evt_data)
{
	int rc = 0;
	struct cam_ctx_request *req;
	struct cam_ctx_request *req = NULL;
	struct cam_isp_ctx_req *req_isp;
	struct cam_context *ctx = ctx_isp->base;

	if (ctx->state != CAM_CTX_ACTIVATED) {
	if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) {
		CAM_DBG(CAM_ISP, "invalid RUP");
		goto end;
	}
@@ -560,6 +661,11 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp,
				CAM_ISP_CTX_ACTIVATED_EPOCH;
		}
	}
	if (req != NULL) {
		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
			CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
			req->request_id);
	}
end:
	return rc;
}
@@ -627,6 +733,15 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
	CAM_DBG(CAM_ISP, "next substate %d",
		ctx_isp->substate_activated);
end:
	if (request_id == 0) {
		req = list_last_entry(&ctx->active_req_list,
			struct cam_ctx_request, list);
		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
			CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id);
	} else {
		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
			CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, request_id);
	}
	return 0;
}

@@ -649,6 +764,7 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
	int rc = 0;
	struct cam_context                    *ctx = ctx_isp->base;
	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
	struct cam_ctx_request *req;

	if (!evt_data) {
		CAM_ERR(CAM_ISP, "in valid sof event data");
@@ -663,6 +779,10 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp,
	else
		CAM_DBG(CAM_ISP, "Still need to wait for the buf done");

	req = list_last_entry(&ctx->active_req_list,
		struct cam_ctx_request, list);
	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
		CAM_ISP_STATE_CHANGE_TRIGGER_SOF, ctx->req_list->request_id);
	CAM_DBG(CAM_ISP, "next substate %d",
		ctx_isp->substate_activated);

@@ -761,6 +881,10 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
	req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request,
		list);
	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
		CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id);
	return 0;
}

@@ -772,6 +896,9 @@ static int __cam_isp_ctx_buf_done_in_bubble_applied(
		(struct cam_isp_hw_done_event_data *) evt_data;

	rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
		CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
		ctx_isp->base->req_list->request_id);
	return rc;
}

@@ -894,6 +1021,14 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
		rc = -EFAULT;
	}


	list_del_init(&req->list);
	list_add(&req->list, &ctx->pending_req_list);
	/* might need to check if active list is empty */
	if (req != NULL) {
		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
			CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req->request_id);
	}
	CAM_DBG(CAM_ISP, "Exit");
	return rc;
}
@@ -1014,7 +1149,7 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
	struct cam_ctx_request          *active_req;
	struct cam_isp_ctx_req          *req_isp;
	struct cam_isp_ctx_req          *active_req_isp;
	struct cam_isp_context          *ctx_isp;
	struct cam_isp_context          *ctx_isp = NULL;
	struct cam_hw_config_args        cfg;

	if (list_empty(&ctx->pending_req_list)) {
@@ -1088,6 +1223,11 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
		spin_unlock_bh(&ctx->lock);
	}
end:
	if (ctx_isp != NULL) {
		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
			CAM_ISP_STATE_CHANGE_TRIGGER_SOF,
			ctx->req_list->request_id);
	}
	return rc;
}

@@ -2439,6 +2579,7 @@ static int __cam_isp_ctx_handle_irq_in_activated(void *context,
	} else {
		CAM_DBG(CAM_ISP, "No handle function for substate %d",
			ctx_isp->substate_activated);
		__cam_isp_ctx_dump_state_monitor_array(ctx_isp);
	}
	CAM_DBG(CAM_ISP, "Exit: State %d Substate %d",
		 ctx->state, ctx_isp->substate_activated);
@@ -2552,6 +2693,12 @@ int cam_isp_context_init(struct cam_isp_context *ctx,
	ctx_base->state_machine = cam_isp_ctx_top_state_machine;
	ctx_base->ctx_priv = ctx;

	/* initializing current state for error logging */
	for (i = 0; i < CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; i++) {
		ctx->cam_isp_ctx_state_monitor[i].curr_state =
		CAM_ISP_CTX_ACTIVATED_MAX;
	}
	atomic64_set(&ctx->state_monitor_head, -1);
err:
	return rc;
}
+60 −18
Original line number Diff line number Diff line
@@ -28,11 +28,16 @@
#define CAM_ISP_CTX_RES_MAX                     20

/*
 * Maxiimum configuration entry size  - This is based on the
 * Maximum configuration entry size  - This is based on the
 * worst case DUAL IFE use case plus some margin.
 */
#define CAM_ISP_CTX_CFG_MAX                     22

/*
 * Maximum entries in state monitoring array for error logging
 */
#define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES   20

/* forward declaration */
struct cam_isp_context;

@@ -56,6 +61,19 @@ enum cam_isp_ctx_activated_substate {
	CAM_ISP_CTX_ACTIVATED_MAX,
};

/**
 * enum cam_isp_state_change_trigger - Different types of ISP events
 *
 */
enum cam_isp_state_change_trigger {
	CAM_ISP_STATE_CHANGE_TRIGGER_ERROR,
	CAM_ISP_STATE_CHANGE_TRIGGER_SOF,
	CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
	CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
	CAM_ISP_STATE_CHANGE_TRIGGER_EOF,
	CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
	CAM_ISP_STATE_CHANGE_TRIGGER_MAX
};

/**
 * struct cam_isp_ctx_irq_ops - Function table for handling IRQ callbacks
@@ -100,6 +118,25 @@ struct cam_isp_ctx_req {
	struct cam_isp_prepare_hw_update_data hw_update_data;
};

/**
 * struct cam_isp_context_state_monitor - ISP context state
 *                                        monitoring for
 *                                        debug purposes
 *
 *@curr_state:          Current sub state that received req
 *@req_type:            Event type of incoming req
 *@req_id:              Request id
 *@evt_time_stamp       Current time stamp
 *
 */
struct cam_isp_context_state_monitor {
	enum cam_isp_ctx_activated_substate  curr_state;
	enum cam_isp_state_change_trigger    trigger;
	uint32_t                             req_id;
	int64_t                              frame_id;
	uint64_t                             evt_time_stamp;
};

/**
 * struct cam_isp_context   -  ISP context object
 *
@@ -114,10 +151,12 @@ struct cam_isp_ctx_req {
 * @sof_timestamp_val:         Captured time stamp value at sof hw event
 * @active_req_cnt:            Counter for the active request
 * @reported_req_id:           Last reported request id
 * @subscribe_event:       The irq event mask that CRM subscribes to, IFE will
 *                         invoke CRM cb at those event.
 * @subscribe_event:           The irq event mask that CRM subscribes to, IFE
 *                             will invoke CRM cb at those event.
 * @last_applied_req_id:       Last applied request id
 * @frame_skip_count:          Number of frame to skip before change state
 * @state_monitor_head:        Write index to the state monitoring array
 * @cam_isp_ctx_state_monitor: State monitoring array
 *
 */
struct cam_isp_context {
@@ -138,6 +177,9 @@ struct cam_isp_context {
	uint32_t                         subscribe_event;
	int64_t                          last_applied_req_id;
	uint32_t                         frame_skip_count;
	atomic64_t                       state_monitor_head;
	struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
		CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES];
};

/**