msm: camera: sof freeze enhancement

Enable CSID IRQ dynamically and add sof recover logic,
in case kernel get sof freeze hints from userspace,will
enable IRQs to monitor the status of moduels,if sof recovers
after 2.5 secs then kernel get MSM_SD_UNNOTIFY_FREEZE to disable
all the IRQs.

CRs-Fixed: 973732
Change-Id: I7aa6dcd60e0858258c40c3d6517e2974e6e2b722
Signed-off-by: Ramesh V <ramev@codeaurora.org>
This commit is contained in:
Ramesh V 2016-02-04 15:56:23 +05:30 committed by David Keitel
parent 99658ec7e3
commit 79e5686c6b
15 changed files with 115 additions and 21 deletions

View file

@ -16,7 +16,7 @@
#include "msm_isp_axi_util.h"
#define HANDLE_TO_IDX(handle) (handle & 0xFF)
#define ISP_SOF_DEBUG_COUNT 0
#define ISP_SOF_DEBUG_COUNT 5
static int msm_isp_update_dual_HW_ms_info_at_start(
struct vfe_device *vfe_dev,

View file

@ -1088,6 +1088,8 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
vfe_dev->isp_raw1_debug = 0;
vfe_dev->isp_raw2_debug = 0;
break;
case MSM_SD_UNNOTIFY_FREEZE:
break;
case MSM_SD_SHUTDOWN:
while (vfe_dev->vfe_open_cnt != 0)
msm_isp_close_node(sd, NULL);

View file

@ -46,7 +46,7 @@
#define ISPIF_TIMEOUT_SLEEP_US 1000
#define ISPIF_TIMEOUT_ALL_US 1000000
#define ISPIF_SOF_DEBUG_COUNT 0
#define ISPIF_SOF_DEBUG_COUNT 5
#undef CDBG
#ifdef CONFIG_MSMB_CAMERA_DEBUG

View file

@ -503,12 +503,16 @@ static inline int __msm_sd_close_subdevs(struct msm_sd_subdev *msm_sd,
return 0;
}
static inline int __msm_sd_notify_freeze_subdevs(struct msm_sd_subdev *msm_sd)
static inline int __msm_sd_notify_freeze_subdevs(struct msm_sd_subdev *msm_sd,
int enable)
{
struct v4l2_subdev *sd;
sd = &msm_sd->sd;
v4l2_subdev_call(sd, core, ioctl, MSM_SD_NOTIFY_FREEZE, NULL);
if (enable)
v4l2_subdev_call(sd, core, ioctl, MSM_SD_NOTIFY_FREEZE, NULL);
else
v4l2_subdev_call(sd, core, ioctl, MSM_SD_UNNOTIFY_FREEZE, NULL);
return 0;
}
@ -716,10 +720,18 @@ static long msm_private_ioctl(struct file *file, void *fh,
break;
case MSM_CAM_V4L2_IOCTL_NOTIFY_DEBUG: {
pr_err("Notifying subdevs about potential sof freeze\n");
if (event_data->status) {
pr_err("%s:Notifying subdevs about potential sof freeze\n",
__func__);
} else {
pr_err("%s:Notifying subdevs about sof recover\n",
__func__);
}
if (!list_empty(&msm_v4l2_dev->subdevs)) {
list_for_each_entry(msm_sd, &ordered_sd_list, list)
__msm_sd_notify_freeze_subdevs(msm_sd);
__msm_sd_notify_freeze_subdevs(msm_sd,
event_data->status);
}
}
break;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, 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
@ -442,6 +442,8 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
case VIDIOC_MSM_BUF_MNGR_FLUSH:
rc = msm_generic_buf_mngr_flush(buf_mngr_dev, argp);
break;
case MSM_SD_UNNOTIFY_FREEZE:
break;
case MSM_SD_SHUTDOWN:
msm_buf_mngr_sd_shutdown(buf_mngr_dev, argp);
break;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2016, 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
@ -37,6 +37,9 @@ struct msm_sd_close_ioctl {
#define MSM_SD_NOTIFY_FREEZE \
_IOWR('V', BASE_VIDIOC_PRIVATE + 30, struct msm_sd_close_ioctl)
#define MSM_SD_UNNOTIFY_FREEZE \
_IOWR('V', BASE_VIDIOC_PRIVATE + 31, struct msm_sd_close_ioctl)
/*
* This is used to install Sequence in msm_sd_register.
* During msm_close, proper close sequence will be triggered.

View file

@ -3332,6 +3332,8 @@ STREAM_BUFF_END:
}
case MSM_SD_NOTIFY_FREEZE:
break;
case MSM_SD_UNNOTIFY_FREEZE:
break;
case MSM_SD_SHUTDOWN:
CPP_DBG("MSM_SD_SHUTDOWN\n");
mutex_unlock(&cpp_dev->mutex);
@ -4075,6 +4077,8 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file,
break;
case MSM_SD_NOTIFY_FREEZE:
break;
case MSM_SD_UNNOTIFY_FREEZE:
break;
case MSM_SD_SHUTDOWN:
cmd = MSM_SD_SHUTDOWN;
break;
@ -4107,6 +4111,8 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file,
break;
case MSM_SD_NOTIFY_FREEZE:
break;
case MSM_SD_UNNOTIFY_FREEZE:
break;
default:
pr_err_ratelimited("%s: unsupported compat type :%d\n",
__func__, cmd);

View file

@ -1487,6 +1487,8 @@ static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
return msm_actuator_config(a_ctrl, argp);
case MSM_SD_NOTIFY_FREEZE:
return 0;
case MSM_SD_UNNOTIFY_FREEZE:
return 0;
case MSM_SD_SHUTDOWN:
if (!a_ctrl->i2c_client.i2c_func_tbl) {
pr_err("a_ctrl->i2c_client.i2c_func_tbl NULL\n");

View file

@ -1698,6 +1698,8 @@ static long msm_cci_subdev_ioctl(struct v4l2_subdev *sd,
break;
case MSM_SD_NOTIFY_FREEZE:
break;
case MSM_SD_UNNOTIFY_FREEZE:
break;
case MSM_SD_SHUTDOWN: {
struct msm_camera_cci_ctrl ctrl_cmd;
ctrl_cmd.cmd = MSM_CCI_RELEASE;

View file

@ -196,6 +196,27 @@ static void msm_csid_set_debug_reg(struct csid_device *csid_dev,
struct msm_camera_csid_params *csid_params) {}
#endif
static void msm_csid_set_sof_freeze_debug_reg(struct csid_device *csid_dev)
{
uint32_t val = 0;
if (csid_dev->csid_3p_enabled == 1) {
val = ((1 << csid_dev->current_csid_params.lane_cnt) - 1) <<
csid_dev->ctrl_reg->
csid_reg.csid_err_lane_overflow_offset_3p;
} else {
val = ((1 << csid_dev->current_csid_params.lane_cnt) - 1) <<
csid_dev->ctrl_reg->
csid_reg.csid_err_lane_overflow_offset_2p;
}
val |= csid_dev->ctrl_reg->csid_reg.csid_irq_mask_val;
val |= SHORT_PKT_OFFSET;
msm_camera_io_w(val, csid_dev->base +
csid_dev->ctrl_reg->csid_reg.csid_irq_mask_addr);
msm_camera_io_w(val, csid_dev->base +
csid_dev->ctrl_reg->csid_reg.csid_irq_clear_cmd_addr);
}
static int msm_csid_reset(struct csid_device *csid_dev)
{
int32_t rc = 0;
@ -417,7 +438,7 @@ static irqreturn_t msm_csid_irq(int irq_num, void *data)
}
irq = msm_camera_io_r(csid_dev->base +
csid_dev->ctrl_reg->csid_reg.csid_irq_status_addr);
CDBG("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
pr_err_ratelimited("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
__func__, csid_dev->pdev->id, irq);
if (irq & (0x1 <<
csid_dev->ctrl_reg->csid_reg.csid_rst_done_irq_bitshift))
@ -733,6 +754,7 @@ static int32_t msm_csid_cmd(struct csid_device *csid_dev, void __user *arg)
}
csid_params.lut_params.vc_cfg[i] = vc_cfg;
}
csid_dev->current_csid_params = csid_params;
csid_dev->csid_sof_debug = SOF_DEBUG_DISABLE;
rc = msm_csid_config(csid_dev, &csid_params);
MEM_CLEAN:
@ -768,6 +790,7 @@ static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
{
int rc = -ENOIOCTLCMD;
struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
mutex_lock(&csid_dev->mutex);
CDBG("%s:%d id %d\n", __func__, __LINE__, csid_dev->pdev->id);
switch (cmd) {
@ -780,7 +803,15 @@ static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
case MSM_SD_NOTIFY_FREEZE:
if (csid_dev->csid_state != CSID_POWER_UP)
break;
csid_dev->csid_sof_debug = SOF_DEBUG_ENABLE;
if (csid_dev->csid_sof_debug == SOF_DEBUG_DISABLE) {
csid_dev->csid_sof_debug = SOF_DEBUG_ENABLE;
msm_csid_set_sof_freeze_debug_reg(csid_dev);
}
break;
case MSM_SD_UNNOTIFY_FREEZE:
if (csid_dev->csid_state != CSID_POWER_UP)
break;
csid_dev->csid_sof_debug = SOF_DEBUG_DISABLE;
break;
case VIDIOC_MSM_CSID_RELEASE:
case MSM_SD_SHUTDOWN:
@ -890,6 +921,7 @@ static int32_t msm_csid_cmd32(struct csid_device *csid_dev, void __user *arg)
csid_params.lut_params.vc_cfg[i] = vc_cfg;
}
rc = msm_csid_config(csid_dev, &csid_params);
csid_dev->current_csid_params = csid_params;
MEM_CLEAN32:
for (i--; i >= 0; i--) {
@ -927,7 +959,15 @@ static long msm_csid_subdev_ioctl32(struct v4l2_subdev *sd,
case MSM_SD_NOTIFY_FREEZE:
if (csid_dev->csid_state != CSID_POWER_UP)
break;
csid_dev->csid_sof_debug = SOF_DEBUG_ENABLE;
if (csid_dev->csid_sof_debug == SOF_DEBUG_DISABLE) {
csid_dev->csid_sof_debug = SOF_DEBUG_ENABLE;
msm_csid_set_sof_freeze_debug_reg(csid_dev);
}
break;
case MSM_SD_UNNOTIFY_FREEZE:
if (csid_dev->csid_state != CSID_POWER_UP)
break;
csid_dev->csid_sof_debug = SOF_DEBUG_DISABLE;
break;
case VIDIOC_MSM_CSID_RELEASE:
case MSM_SD_SHUTDOWN:

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2016, 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
@ -112,6 +112,7 @@ struct csid_device {
int32_t regulator_count;
uint8_t is_testmode;
struct msm_camera_csid_testmode_parms testmode_params;
struct msm_camera_csid_params current_csid_params;
uint32_t csid_sof_debug;
uint32_t csid_lane_cnt;
};

View file

@ -46,6 +46,7 @@
#define CSI_3PHASE_HW 1
#define MAX_LANES 4
#define CLOCK_OFFSET 0x700
#define CSIPHY_SOF_DEBUG_COUNT 3
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
@ -636,6 +637,13 @@ static irqreturn_t msm_csiphy_irq(int irq_num, void *data)
int i;
struct csiphy_device *csiphy_dev = data;
if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_ENABLE) {
if (csiphy_dev->csiphy_sof_debug_count < CSIPHY_SOF_DEBUG_COUNT)
csiphy_dev->csiphy_sof_debug_count++;
else
return IRQ_HANDLED;
}
for (i = 0; i < csiphy_dev->num_irq_registers; i++) {
irq = msm_camera_io_r(
csiphy_dev->base +
@ -645,7 +653,8 @@ static irqreturn_t msm_csiphy_irq(int irq_num, void *data)
csiphy_dev->base +
csiphy_dev->ctrl_reg->csiphy_reg.
mipi_csiphy_interrupt_clear0_addr + 0x4*i);
CDBG("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
pr_err_ratelimited(
"%s CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x\n",
__func__, csiphy_dev->pdev->id, i, irq);
msm_camera_io_w(0x0,
csiphy_dev->base +
@ -809,7 +818,7 @@ static int msm_csiphy_init(struct csiphy_device *csiphy_dev)
rc = -ENOMEM;
return rc;
}
csiphy_dev->csiphy_sof_debug_count = 0;
CDBG("%s:%d called\n", __func__, __LINE__);
if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) {
pr_err("%s: csiphy invalid state %d\n", __func__,
@ -1110,7 +1119,10 @@ static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg)
csiphy_dev->ctrl_reg->csiphy_reg.
mipi_csiphy_glbl_pwr_cfg_addr);
}
if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_ENABLE) {
csiphy_dev->csiphy_sof_debug = SOF_DEBUG_DISABLE;
disable_irq(csiphy_dev->irq->start);
}
if (csiphy_dev->hw_dts_version <= CSIPHY_VERSION_V22) {
msm_cam_clk_enable(&csiphy_dev->pdev->dev,
csiphy_dev->csiphy_clk_info, csiphy_dev->csiphy_clk,
@ -1167,8 +1179,6 @@ static int32_t msm_csiphy_cmd(struct csiphy_device *csiphy_dev, void *arg)
rc = -EFAULT;
break;
}
if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_ENABLE)
disable_irq(csiphy_dev->irq->start);
rc = msm_csiphy_release(csiphy_dev, &csi_lane_params);
break;
default:
@ -1214,8 +1224,17 @@ static long msm_csiphy_subdev_ioctl(struct v4l2_subdev *sd,
if (!csiphy_dev || !csiphy_dev->ctrl_reg ||
!csiphy_dev->ref_count)
break;
csiphy_dev->csiphy_sof_debug = SOF_DEBUG_ENABLE;
enable_irq(csiphy_dev->irq->start);
if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_DISABLE) {
csiphy_dev->csiphy_sof_debug = SOF_DEBUG_ENABLE;
enable_irq(csiphy_dev->irq->start);
}
break;
case MSM_SD_UNNOTIFY_FREEZE:
if (!csiphy_dev || !csiphy_dev->ctrl_reg ||
!csiphy_dev->ref_count)
break;
csiphy_dev->csiphy_sof_debug = SOF_DEBUG_DISABLE;
disable_irq(csiphy_dev->irq->start);
break;
default:
pr_err_ratelimited("%s: command not found\n", __func__);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2016, 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
@ -163,6 +163,7 @@ struct csiphy_device {
uint8_t csiphy_3phase;
uint8_t num_irq_registers;
uint32_t csiphy_sof_debug;
uint32_t csiphy_sof_debug_count;
};
#define VIDIOC_MSM_CSIPHY_RELEASE \

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2009-2016, 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
@ -655,6 +655,8 @@ static long msm_flash_subdev_ioctl(struct v4l2_subdev *sd,
return msm_flash_config(fctrl, argp);
case MSM_SD_NOTIFY_FREEZE:
return 0;
case MSM_SD_UNNOTIFY_FREEZE:
return 0;
case MSM_SD_SHUTDOWN:
if (!fctrl->func_tbl) {
pr_err("fctrl->func_tbl NULL\n");

View file

@ -316,6 +316,8 @@ static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
return 0;
case MSM_SD_NOTIFY_FREEZE:
return 0;
case MSM_SD_UNNOTIFY_FREEZE:
return 0;
default:
return -ENOIOCTLCMD;
}