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

Commit 763fd3e6 authored by Junzhe Zou's avatar Junzhe Zou Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: Handle bus error in bottom half



Configure the debug status registers during bus init
and read the value of debug status during bottom half
processing when the bus error occurs. Print out
the client causing the bus violation based on debug
status value.

Change-Id: Ibf6ac60affc7102e2495610213ef2c9504c7c54e
Signed-off-by: default avatarJunzhe Zou <jnzhezou@codeaurora.org>
Signed-off-by: default avatarVishalsingh Hajeri <vhajeri@codeaurora.org>
Signed-off-by: default avatarVenkat Chinta <vchinta@codeaurora.org>
parent f068b374
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ struct cam_vfe_top_irq_evt_payload {
 *
 * @list:                    list_head node for the payload
 * @core_index:              Index of VFE HW that generated this IRQ event
 * @debug_status_0:          Value of debug status_0 register at time of IRQ
 * @evt_id:                  IRQ event
 * @irq_reg_val:             IRQ and Error register values, read when IRQ was
 *                           handled
@@ -247,6 +248,7 @@ struct cam_vfe_top_irq_evt_payload {
struct cam_vfe_bus_irq_evt_payload {
	struct list_head            list;
	uint32_t                    core_index;
	uint32_t                    debug_status_0;
	uint32_t                    evt_id;
	uint32_t                    irq_reg_val[CAM_IFE_BUS_IRQ_REGISTERS_MAX];
	uint32_t                    error_type;
+2 −0
Original line number Diff line number Diff line
@@ -234,6 +234,8 @@ static struct cam_vfe_bus_ver2_hw_info vfe170_bus_hw_info = {
		.addr_sync_cfg                = 0x0000207C,
		.addr_sync_frame_hdr          = 0x00002080,
		.addr_sync_no_sync            = 0x00002084,
		.debug_status_cfg             = 0x0000226C,
		.debug_status_0               = 0x00002270,
	},
	.num_client = 20,
	.bus_client_reg = {
+125 −6
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ static const char drv_name[] = "vfe_bus";

#define CAM_VFE_BUS_VER2_PAYLOAD_MAX             256

#define CAM_VFE_BUS_SET_DEBUG_REG                0x82

#define CAM_VFE_RDI_BUS_DEFAULT_WIDTH               0xFF01
#define CAM_VFE_RDI_BUS_DEFAULT_STRIDE              0xFF01
#define CAM_VFE_BUS_INTRA_CLIENT_MASK               0x3
@@ -205,6 +207,7 @@ struct cam_vfe_bus_ver2_priv {

	uint32_t                            irq_handle;
	uint32_t                            error_irq_handle;
	void                               *tasklet_info;
};

static int cam_vfe_bus_process_cmd(
@@ -1227,6 +1230,99 @@ static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
	return rc;
}


static int cam_vfe_bus_err_bottom_half(void *ctx_priv,
	void *evt_payload_priv)
{
	struct cam_vfe_bus_irq_evt_payload *evt_payload;
	struct cam_vfe_bus_ver2_common_data *common_data;
	uint32_t val = 0;

	if (!ctx_priv || !evt_payload_priv)
		return -EINVAL;

	evt_payload = evt_payload_priv;
	common_data = evt_payload->ctx;

	val = evt_payload->debug_status_0;
	CAM_ERR(CAM_ISP, "Bus Violation: debug_status_0 = 0x%x", val);

	if (val & 0x01)
		CAM_INFO(CAM_ISP, "RDI 0 violation");

	if (val & 0x02)
		CAM_INFO(CAM_ISP, "RDI 1 violation");

	if (val & 0x04)
		CAM_INFO(CAM_ISP, "RDI 2 violation");

	if (val & 0x08)
		CAM_INFO(CAM_ISP, "VID Y 1:1 UBWC violation");

	if (val & 0x010)
		CAM_INFO(CAM_ISP, "VID C 1:1 UBWC violation");

	if (val & 0x020)
		CAM_INFO(CAM_ISP, "VID YC 4:1 violation");

	if (val & 0x040)
		CAM_INFO(CAM_ISP, "VID YC 16:1 violation");

	if (val & 0x080)
		CAM_INFO(CAM_ISP, "FD Y violation");

	if (val & 0x0100)
		CAM_INFO(CAM_ISP, "FD C violation");

	if (val & 0x0200)
		CAM_INFO(CAM_ISP, "RAW DUMP violation");

	if (val & 0x0400)
		CAM_INFO(CAM_ISP, "PDAF violation");

	if (val & 0x0800)
		CAM_INFO(CAM_ISP, "STATs HDR BE violation");

	if (val & 0x01000)
		CAM_INFO(CAM_ISP, "STATs HDR BHIST violation");

	if (val & 0x02000)
		CAM_INFO(CAM_ISP, "STATs TINTLESS BG violation");

	if (val & 0x04000)
		CAM_INFO(CAM_ISP, "STATs BF violation");

	if (val & 0x08000)
		CAM_INFO(CAM_ISP, "STATs AWB BG UBWC violation");

	if (val & 0x010000)
		CAM_INFO(CAM_ISP, "STATs BHIST violation");

	if (val & 0x020000)
		CAM_INFO(CAM_ISP, "STATs RS violation");

	if (val & 0x040000)
		CAM_INFO(CAM_ISP, "STATs CS violation");

	if (val & 0x080000)
		CAM_INFO(CAM_ISP, "STATs IHIST violation");

	if (val & 0x0100000)
		CAM_INFO(CAM_ISP, "DISP Y 1:1 UBWC violation");

	if (val & 0x0200000)
		CAM_INFO(CAM_ISP, "DISP C 1:1 UBWC violation");

	if (val & 0x0400000)
		CAM_INFO(CAM_ISP, "DISP YC 4:1 violation");

	if (val & 0x0800000)
		CAM_INFO(CAM_ISP, "DISP YC 16:1 violation");

	cam_vfe_bus_put_evt_payload(common_data, &evt_payload);
	return 0;
}

static int cam_vfe_bus_init_wm_resource(uint32_t index,
	struct cam_vfe_bus_ver2_priv    *ver2_bus_priv,
	struct cam_vfe_bus_ver2_hw_info *ver2_hw_info,
@@ -1927,6 +2023,7 @@ static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
	}
	mutex_unlock(&rsrc_data->common_data->bus_mutex);

	ver2_bus_priv->tasklet_info = acq_args->tasklet;
	rsrc_data->num_wm = num_wm;
	rsrc_node->res_id = out_acquire_args->out_port_info->res_type;
	rsrc_node->tasklet_info = acq_args->tasklet;
@@ -2267,9 +2364,10 @@ static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
static int cam_vfe_bus_error_irq_top_half(uint32_t evt_id,
	struct cam_irq_th_payload *th_payload)
{
	int i = 0;
	int i = 0, rc = 0;
	struct cam_vfe_bus_ver2_priv *bus_priv =
		th_payload->handler_priv;
	struct cam_vfe_bus_irq_evt_payload *evt_payload;

	CAM_ERR_RATE_LIMIT(CAM_ISP, "Bus Err IRQ");
	for (i = 0; i < th_payload->num_registers; i++) {
@@ -2280,8 +2378,25 @@ static int cam_vfe_bus_error_irq_top_half(uint32_t evt_id,
	cam_irq_controller_disable_irq(bus_priv->common_data.bus_irq_controller,
		bus_priv->error_irq_handle);

	/* Returning error stops from enqueuing bottom half */
	return -EFAULT;
	rc  = cam_vfe_bus_get_evt_payload(&bus_priv->common_data, &evt_payload);
	if (rc) {
		CAM_ERR_RATE_LIMIT(CAM_ISP, "Cannot get payload");
		return rc;
	}

	for (i = 0; i < th_payload->num_registers; i++)
		evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];

	evt_payload->core_index = bus_priv->common_data.core_index;
	evt_payload->evt_id  = evt_id;
	evt_payload->ctx = &bus_priv->common_data;
	evt_payload->debug_status_0 = cam_io_r_mb(
		bus_priv->common_data.mem_base +
		bus_priv->common_data.common_reg->debug_status_0);

	th_payload->evt_payload_priv = evt_payload;

	return rc;
}

static int cam_vfe_bus_update_wm(void *priv, void *cmd_args,
@@ -2767,15 +2882,19 @@ static int cam_vfe_bus_init_hw(void *hw_priv,
		bus_error_irq_mask,
		bus_priv,
		cam_vfe_bus_error_irq_top_half,
		NULL,
		NULL,
		NULL);
		cam_vfe_bus_err_bottom_half,
		bus_priv->tasklet_info,
		&tasklet_bh_api);

	if (bus_priv->irq_handle <= 0) {
		CAM_ERR(CAM_ISP, "Failed to subscribe BUS IRQ");
		return -EFAULT;
	}

	/*Set Debug Registers*/
	cam_io_w_mb(CAM_VFE_BUS_SET_DEBUG_REG, bus_priv->common_data.mem_base +
		bus_priv->common_data.common_reg->debug_status_cfg);

	/* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
	cam_io_w_mb(0x0, bus_priv->common_data.mem_base +
		bus_priv->common_data.common_reg->addr_sync_frame_hdr);
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -83,6 +83,8 @@ struct cam_vfe_bus_ver2_reg_offset_common {
	uint32_t addr_sync_cfg;
	uint32_t addr_sync_frame_hdr;
	uint32_t addr_sync_no_sync;
	uint32_t debug_status_cfg;
	uint32_t debug_status_0;
};

/*