Jetson Tk1 read CSI STATUS registry value causes kernel freeze

Hi support,

We are facing to a kernel freeze when we try to read a registry value.

static void vi2_capture_error_status(struct tegra_camera_dev *cam)
{
        u32 val = 0;

#ifdef DEBUG
        val = TC_VI_REG_RD(cam, TEGRA_CSI_DEBUG_COUNTER_0);
        pr_err("TEGRA_CSI_DEBUG_COUNTER_0 0x%08x\n", val);
#endif
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_A_STATUS);
        pr_err("TEGRA_CSI_CSI_CIL_A_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CILA_STATUS);
        pr_err("TEGRA_CSI_CSI_CILA_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_B_STATUS);
        pr_err("TEGRA_CSI_CSI_CIL_B_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_C_STATUS);
        pr_err("TEGRA_CSI_CSI_CIL_C_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_D_STATUS);
        pr_err("TEGRA_CSI_CSI_CIL_D_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_E_STATUS);
        pr_err("TEGRA_CSI_CSI_CIL_E_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS);
        pr_err("TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS);
        pr_err("TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_VI_CSI_0_ERROR_STATUS);
        pr_err("TEGRA_VI_CSI_0_ERROR_STATUS 0x%08x\n", val);
        val = TC_VI_REG_RD(cam, TEGRA_VI_CSI_1_ERROR_STATUS);
        pr_err("TEGRA_VI_CSI_1_ERROR_STATUS 0x%08x\n", val);
}

When the readl function is invoked to read a CSI Status registry, the kernel hangs.
We get the following output on serial console:

[  840.298821] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
[  840.299818] MSELECT error detected! status=0x3
[  840.303089] MSELECT error detected! status=0x3
[  840.309785] MSELECT error detected! status=0x3
[  840.313216] MSELECT error detected! status=0x3
[  840.317673] MSELECT error detected! status=0x3
[  840.321241] MSELECT error detected! status=0x3
[  840.328276] MSELECT error detected! status=0x3
[  840.333134] MSELECT error detected! status=0x3
[  840.338080] MSELECT error detected! status=0x3
[  840.343026] MSELECT error detected! status=0x3
[  840.347953] MSELECT error detected! status=0x3
[  840.352898] MSELECT error detected! status=0x3
[  840.357694] MSELECT error detected! status=0x3
[  840.362680] MSELECT error detected! status=0x3
[  840.367490] MSELECT error detected! status=0x3

Questions

  1. Why are we not able to read these registries value ?
  2. Why the TEGRA_CSI_CSI_CIL_A_INTERRUPT_MASK is not set on vi2.c so that we could get synchronous error events?

Infos
*Jetson TK1 R21.5
*kernel : 3.10.40
*We are using a HDMI to CSI-2 Bridge (From a third party manufacturer) on the Jetson TK1.
The driver tc358743 is used for this card.

Best regards,

Hi,

In recent version of vi2 driver (http://nv-tegra.nvidia.com/gitweb/?p=linux-3.10.git;a=blob;f=drivers/media/platform/soc_camera/tegra_camera/vi2.c;h=aeecd41fd1a92b2b80890ec668c12414c8194300;hb=4206e3f9c9b3a1757c36bb798ca751c09e2db8c5), the function vi2_capture_error_status read on the registry and write error on it if its occurs.

We tried to do the same on our vi2_capture_error_status function

static void vi2_capture_error_status(struct tegra_camera_dev *cam)
{
        u32 val = 0;

#ifdef DEBUG
        val = TC_VI_REG_RD(cam, TEGRA_CSI_DEBUG_COUNTER_0);
        pr_err("TEGRA_CSI_DEBUG_COUNTER_0 0x%08x\n", val);
#endif
        // /!\ CAUSE MSELECT ERROR => KERNEL HANG
        val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_A_STATUS);
        if(val)
                TC_VI_REG_WT(cam, TEGRA_CSI_CSI_CIL_A_STATUS, val);
....

But the kernel still hangs when we try to read the registry value.

Hi Romary
We are investigate it. Will update here once get result.

We made a sysfs interface to test syncpt statusregister, and it always make the system crash.

Any solution on your side ?

hello Romary,

could you try to use 3rdparty tool (devmem2) to access the register directly?
please download the TK1 TRM to know the register address. http://developer.nvidia.com/embedded/dlc/TK1-TRM
thanks

Romary
We can see the system hang up while access those CSI register. We are debugging, this problem could not easy to fixed.

Hi Romary
Access the REG cause system hang up during the power and clock is off. Could you try modify the tegra_camera_deactivate() locate the …/soc_camera/tegra_camera/common.c to skip all the deactivate thing to try.

We are using this patch (adding sysfs) to access register at anytime, but it make the system freeze :

diff --git a/drivers/media/platform/soc_camera/tegra_camera/vi2.c b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
index 4836692..a514af5 100644
--- a/drivers/media/platform/soc_camera/tegra_camera/vi2.c
+++ b/drivers/media/platform/soc_camera/tegra_camera/vi2.c
@@ -1442,3 +1443,158 @@ int vi2_register(struct tegra_camera_dev *cam)
 
 	return 0;
 }
+
+static ssize_t show_tegra_csi_debug_counter_0(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_DEBUG_COUNTER_0);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_debug_counter_0, S_IRUGO, show_tegra_csi_debug_counter_0, NULL);
+
+static ssize_t show_tegra_csi_csi_cil_a(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_A_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_cil_a, S_IRUGO, show_tegra_csi_csi_cil_a, NULL);
+
+static ssize_t show_tegra_csi_csi_cila(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CILA_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_cila, S_IRUGO, show_tegra_csi_csi_cila, NULL);
+
+static ssize_t show_tegra_csi_csi_cil_b(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_B_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_cil_b, S_IRUGO, show_tegra_csi_csi_cil_b, NULL);
+
+static ssize_t show_tegra_csi_csi_cil_c(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_C_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_cil_c, S_IRUGO, show_tegra_csi_csi_cil_c, NULL);
+
+static ssize_t show_tegra_csi_csi_cil_d(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_D_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_cil_d, S_IRUGO, show_tegra_csi_csi_cil_d, NULL);
+
+static ssize_t show_tegra_csi_csi_cil_e(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_CIL_E_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_cil_e, S_IRUGO, show_tegra_csi_csi_cil_e, NULL);
+
+static ssize_t show_tegra_csi_csi_pixel_parser_a_status(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_A_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_pixel_parser_a_status, S_IRUGO, show_tegra_csi_csi_pixel_parser_a_status, NULL);
+
+static ssize_t show_tegra_csi_csi_pixel_parser_b_status(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_CSI_CSI_PIXEL_PARSER_B_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_csi_csi_pixel_parser_b_status, S_IRUGO, show_tegra_csi_csi_pixel_parser_b_status, NULL);
+
+static ssize_t show_tegra_vi_csi_0_error_status(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+	
+	val = TC_VI_REG_RD(cam, TEGRA_VI_CSI_0_ERROR_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_vi_csi_0_error_status, S_IRUGO, show_tegra_vi_csi_0_error_status, NULL);
+
+static ssize_t show_tegra_vi_csi_1_error_status(struct device *dev,
+                              struct device_attribute *attr, char *buf){
+	u32 val=0;
+	struct soc_camera_host *ici = to_soc_camera_host(dev);
+	struct tegra_camera_dev *cam = ici->priv;
+
+	val = TC_VI_REG_RD(cam, TEGRA_VI_CSI_1_ERROR_STATUS);
+
+	return sprintf(buf, "0x%08x\n", val);
+}
+static DEVICE_ATTR(tegra_vi_csi_1_error_status, S_IRUGO, show_tegra_vi_csi_1_error_status, NULL);
+
+
+struct attribute *tegra_vi_sysfs_entries[] = {
+	&dev_attr_tegra_csi_debug_counter_0.attr,
+	&dev_attr_tegra_csi_csi_cil_a.attr,
+	&dev_attr_tegra_csi_csi_cila.attr,
+	&dev_attr_tegra_csi_csi_cil_b.attr,
+	&dev_attr_tegra_csi_csi_cil_c.attr,
+	&dev_attr_tegra_csi_csi_cil_d.attr,
+	&dev_attr_tegra_csi_csi_cil_e.attr,
+	&dev_attr_tegra_csi_csi_pixel_parser_a_status.attr,
+	&dev_attr_tegra_csi_csi_pixel_parser_b_status.attr,
+	&dev_attr_tegra_vi_csi_0_error_status.attr,
+	&dev_attr_tegra_vi_csi_1_error_status.attr,
+	NULL,
+};
+
+
+struct attribute_group show_tegra_vi_attribute_group = {
+        .name = NULL,           /* put in device directory */
+        .attrs = tegra_vi_sysfs_entries,
+};
+
+

@Romary
You need to enable the power and clock as I mention #7, does the debug fs access the REG freeze during the sensor is activation?

Hi Romary,

Have this issue been clarified and fixed?
Any result can be shared?

Thanks