msm: camera: isp: Vote for bandwidth to avoid race condition
Vote for bandwidth before enabling write masters. This ensures no race condition between enabling write masters and bandwidth voting. Change-Id: I235f215908ebf5eb7289c5a7ff2d86d45902fe76 CRs-Fixed: 1112869 Signed-off-by: Rajeev Kulkarni <krajeev@codeaurora.org> Signed-off-by: Shubhraprakash Das <sadas@codeaurora.org>
This commit is contained in:
parent
4e6f40f24c
commit
e543c53234
3 changed files with 60 additions and 68 deletions
|
@ -469,6 +469,7 @@ struct msm_vfe_axi_stream {
|
||||||
*/
|
*/
|
||||||
uint32_t vfe_mask;
|
uint32_t vfe_mask;
|
||||||
uint32_t composite_irq[MSM_ISP_COMP_IRQ_MAX];
|
uint32_t composite_irq[MSM_ISP_COMP_IRQ_MAX];
|
||||||
|
int lpm_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_vfe_axi_composite_info {
|
struct msm_vfe_axi_composite_info {
|
||||||
|
|
|
@ -27,6 +27,9 @@ static void __msm_isp_axi_stream_update(
|
||||||
struct msm_vfe_axi_stream *stream_info,
|
struct msm_vfe_axi_stream *stream_info,
|
||||||
struct msm_isp_timestamp *ts);
|
struct msm_isp_timestamp *ts);
|
||||||
|
|
||||||
|
static int msm_isp_update_stream_bandwidth(
|
||||||
|
struct msm_vfe_axi_stream *stream_info, int enable);
|
||||||
|
|
||||||
#define DUAL_VFE_AND_VFE1(s, v) ((s->stream_src < RDI_INTF_0) && \
|
#define DUAL_VFE_AND_VFE1(s, v) ((s->stream_src < RDI_INTF_0) && \
|
||||||
v->is_split && vfe_dev->pdev->id == ISP_VFE1)
|
v->is_split && vfe_dev->pdev->id == ISP_VFE1)
|
||||||
|
|
||||||
|
@ -2381,46 +2384,42 @@ static void msm_isp_update_intf_stream_cnt(
|
||||||
/*Factor in Q2 format*/
|
/*Factor in Q2 format*/
|
||||||
#define ISP_DEFAULT_FORMAT_FACTOR 6
|
#define ISP_DEFAULT_FORMAT_FACTOR 6
|
||||||
#define ISP_BUS_UTILIZATION_FACTOR 6
|
#define ISP_BUS_UTILIZATION_FACTOR 6
|
||||||
static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
|
static int msm_isp_update_stream_bandwidth(
|
||||||
|
struct msm_vfe_axi_stream *stream_info, int enable)
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
struct msm_vfe_axi_stream *stream_info;
|
uint64_t total_bandwidth = 0;
|
||||||
uint64_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
|
|
||||||
uint32_t num_pix_streams = 0;
|
|
||||||
int vfe_idx;
|
int vfe_idx;
|
||||||
|
struct vfe_device *vfe_dev;
|
||||||
|
|
||||||
for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
|
for (i = 0; i < stream_info->num_isp; i++) {
|
||||||
stream_info = msm_isp_get_stream_common_data(vfe_dev, i);
|
vfe_dev = stream_info->vfe_dev[i];
|
||||||
if (stream_info->state == ACTIVE ||
|
vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev,
|
||||||
stream_info->state == START_PENDING) {
|
stream_info);
|
||||||
vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev,
|
if (enable) {
|
||||||
stream_info);
|
total_bandwidth =
|
||||||
if (stream_info->stream_src < RDI_INTF_0) {
|
vfe_dev->total_bandwidth +
|
||||||
total_pix_bandwidth +=
|
|
||||||
stream_info->bandwidth[vfe_idx];
|
stream_info->bandwidth[vfe_idx];
|
||||||
num_pix_streams++;
|
} else {
|
||||||
} else {
|
total_bandwidth = vfe_dev->total_bandwidth -
|
||||||
total_rdi_bandwidth +=
|
|
||||||
stream_info->bandwidth[vfe_idx];
|
stream_info->bandwidth[vfe_idx];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
vfe_dev->total_bandwidth = total_bandwidth;
|
||||||
|
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
|
||||||
|
(total_bandwidth + vfe_dev->hw_info->min_ab),
|
||||||
|
(total_bandwidth + vfe_dev->hw_info->min_ib));
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
pr_err("%s: update failed rc %d stream src %d vfe dev %d\n",
|
||||||
|
__func__, rc, stream_info->stream_src,
|
||||||
|
vfe_dev->pdev->id);
|
||||||
}
|
}
|
||||||
vfe_dev->total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
|
|
||||||
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
|
|
||||||
(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
|
|
||||||
(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
|
|
||||||
|
|
||||||
if (rc < 0)
|
|
||||||
pr_err("%s: update failed\n", __func__);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
|
int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
uint64_t total_bandwidth = 0;
|
|
||||||
int vfe_idx;
|
|
||||||
uint32_t intf;
|
uint32_t intf;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct msm_vfe_axi_stream *stream_info;
|
struct msm_vfe_axi_stream *stream_info;
|
||||||
|
@ -2444,21 +2443,15 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
|
||||||
intf = SRC_TO_INTF(stream_info->stream_src);
|
intf = SRC_TO_INTF(stream_info->stream_src);
|
||||||
vfe_dev->axi_data.src_info[intf].lpm =
|
vfe_dev->axi_data.src_info[intf].lpm =
|
||||||
ab_ib_vote->lpm_mode;
|
ab_ib_vote->lpm_mode;
|
||||||
if (stream_info->state == ACTIVE) {
|
if (stream_info->lpm_mode) {
|
||||||
vfe_idx =
|
spin_unlock_irqrestore(&stream_info->lock,
|
||||||
msm_isp_get_vfe_idx_for_stream(vfe_dev,
|
flags);
|
||||||
stream_info);
|
continue;
|
||||||
total_bandwidth +=
|
|
||||||
stream_info->bandwidth[
|
|
||||||
vfe_idx];
|
|
||||||
stream_info->state = PAUSED;
|
|
||||||
}
|
}
|
||||||
|
stream_info->lpm_mode = ab_ib_vote->lpm_mode;
|
||||||
spin_unlock_irqrestore(&stream_info->lock, flags);
|
spin_unlock_irqrestore(&stream_info->lock, flags);
|
||||||
|
msm_isp_update_stream_bandwidth(stream_info, 0);
|
||||||
}
|
}
|
||||||
vfe_dev->total_bandwidth -= total_bandwidth;
|
|
||||||
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
|
|
||||||
(vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ab),
|
|
||||||
(vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ib));
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < ab_ib_vote->num_src; i++) {
|
for (i = 0; i < ab_ib_vote->num_src; i++) {
|
||||||
stream_info =
|
stream_info =
|
||||||
|
@ -2470,24 +2463,19 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
|
||||||
intf = SRC_TO_INTF(stream_info->stream_src);
|
intf = SRC_TO_INTF(stream_info->stream_src);
|
||||||
vfe_dev->axi_data.src_info[intf].lpm =
|
vfe_dev->axi_data.src_info[intf].lpm =
|
||||||
ab_ib_vote->lpm_mode;
|
ab_ib_vote->lpm_mode;
|
||||||
if (stream_info->state == PAUSED) {
|
if (stream_info->lpm_mode == 0) {
|
||||||
vfe_idx =
|
spin_unlock_irqrestore(&stream_info->lock,
|
||||||
msm_isp_get_vfe_idx_for_stream(vfe_dev,
|
flags);
|
||||||
stream_info);
|
continue;
|
||||||
total_bandwidth +=
|
|
||||||
stream_info->bandwidth[
|
|
||||||
vfe_idx];
|
|
||||||
stream_info->state = ACTIVE;
|
|
||||||
}
|
}
|
||||||
|
stream_info->lpm_mode = 0;
|
||||||
spin_unlock_irqrestore(&stream_info->lock, flags);
|
spin_unlock_irqrestore(&stream_info->lock, flags);
|
||||||
|
msm_isp_update_stream_bandwidth(stream_info, 1);
|
||||||
}
|
}
|
||||||
vfe_dev->total_bandwidth += total_bandwidth;
|
|
||||||
rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
|
|
||||||
(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
|
|
||||||
(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
|
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msm_isp_init_stream_ping_pong_reg(
|
static int msm_isp_init_stream_ping_pong_reg(
|
||||||
struct msm_vfe_axi_stream *stream_info)
|
struct msm_vfe_axi_stream *stream_info)
|
||||||
{
|
{
|
||||||
|
@ -2896,7 +2884,7 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
|
||||||
* be INACTIVE
|
* be INACTIVE
|
||||||
*/
|
*/
|
||||||
intf = SRC_TO_INTF(stream_info->stream_src);
|
intf = SRC_TO_INTF(stream_info->stream_src);
|
||||||
if ((!vfe_dev->axi_data.src_info[intf].lpm) ||
|
if (stream_info->lpm_mode == 0 &&
|
||||||
stream_info->state != PAUSED) {
|
stream_info->state != PAUSED) {
|
||||||
while (stream_info->state != ACTIVE)
|
while (stream_info->state != ACTIVE)
|
||||||
__msm_isp_axi_stream_update(stream_info,
|
__msm_isp_axi_stream_update(stream_info,
|
||||||
|
@ -2914,16 +2902,14 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
|
||||||
vfe_dev->hw_info->vfe_ops.axi_ops.
|
vfe_dev->hw_info->vfe_ops.axi_ops.
|
||||||
clear_wm_irq_mask(vfe_dev, stream_info);
|
clear_wm_irq_mask(vfe_dev, stream_info);
|
||||||
}
|
}
|
||||||
if (stream_info->state == ACTIVE &&
|
init_completion(&stream_info->inactive_comp);
|
||||||
!vfe_dev->axi_data.src_info[intf].lpm) {
|
stream_info->state = STOP_PENDING;
|
||||||
init_completion(&stream_info->inactive_comp);
|
if (stream_info->lpm_mode ||
|
||||||
stream_info->state = STOP_PENDING;
|
|
||||||
} else if (vfe_dev->axi_data.src_info[intf].lpm ||
|
|
||||||
stream_info->state == PAUSED) {
|
stream_info->state == PAUSED) {
|
||||||
/* don't wait for reg update */
|
/* don't wait for reg update */
|
||||||
stream_info->state = STOP_PENDING;
|
while (stream_info->state != INACTIVE)
|
||||||
msm_isp_axi_stream_enable_cfg(stream_info);
|
__msm_isp_axi_stream_update(stream_info,
|
||||||
stream_info->state = INACTIVE;
|
×tamp);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&stream_info->lock, flags);
|
spin_unlock_irqrestore(&stream_info->lock, flags);
|
||||||
}
|
}
|
||||||
|
@ -2984,6 +2970,8 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
|
||||||
/* clear buffers that are dequeued */
|
/* clear buffers that are dequeued */
|
||||||
for (i = 0; i < num_streams; i++) {
|
for (i = 0; i < num_streams; i++) {
|
||||||
stream_info = streams[i];
|
stream_info = streams[i];
|
||||||
|
if (stream_info->lpm_mode == 0)
|
||||||
|
msm_isp_update_stream_bandwidth(stream_info, 0);
|
||||||
for (bufq_id = 0; bufq_id < VFE_BUF_QUEUE_MAX; bufq_id++) {
|
for (bufq_id = 0; bufq_id < VFE_BUF_QUEUE_MAX; bufq_id++) {
|
||||||
bufq_handle = stream_info->bufq_handle[bufq_id];
|
bufq_handle = stream_info->bufq_handle[bufq_id];
|
||||||
if (!bufq_handle)
|
if (!bufq_handle)
|
||||||
|
@ -2999,12 +2987,6 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (k = 0; k < MAX_VFE; k++) {
|
|
||||||
if (!update_vfes[k])
|
|
||||||
continue;
|
|
||||||
msm_isp_update_stream_bandwidth(update_vfes[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < num_streams; i++) {
|
for (i = 0; i < num_streams; i++) {
|
||||||
stream_info = streams[i];
|
stream_info = streams[i];
|
||||||
intf = SRC_TO_INTF(stream_info->stream_src);
|
intf = SRC_TO_INTF(stream_info->stream_src);
|
||||||
|
@ -3098,7 +3080,14 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
|
||||||
cfg_wm_irq_mask(vfe_dev, stream_info);
|
cfg_wm_irq_mask(vfe_dev, stream_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
intf = SRC_TO_INTF(stream_info->stream_src);
|
intf = SRC_TO_INTF(stream_info->stream_src);
|
||||||
|
stream_info->lpm_mode = vfe_dev_ioctl->
|
||||||
|
axi_data.src_info[intf].lpm;
|
||||||
|
if (stream_info->lpm_mode == 0) {
|
||||||
|
spin_unlock_irqrestore(&stream_info->lock, flags);
|
||||||
|
msm_isp_update_stream_bandwidth(stream_info, 1);
|
||||||
|
spin_lock_irqsave(&stream_info->lock, flags);
|
||||||
|
}
|
||||||
init_completion(&stream_info->active_comp);
|
init_completion(&stream_info->active_comp);
|
||||||
stream_info->state = START_PENDING;
|
stream_info->state = START_PENDING;
|
||||||
msm_isp_update_intf_stream_cnt(stream_info, 1);
|
msm_isp_update_intf_stream_cnt(stream_info, 1);
|
||||||
|
@ -3108,7 +3097,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
|
||||||
vfe_dev_ioctl->pdev->id);
|
vfe_dev_ioctl->pdev->id);
|
||||||
if (src_state) {
|
if (src_state) {
|
||||||
src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
|
src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
|
||||||
if (vfe_dev_ioctl->axi_data.src_info[intf].lpm) {
|
if (stream_info->lpm_mode) {
|
||||||
while (stream_info->state != ACTIVE)
|
while (stream_info->state != ACTIVE)
|
||||||
__msm_isp_axi_stream_update(
|
__msm_isp_axi_stream_update(
|
||||||
stream_info, ×tamp);
|
stream_info, ×tamp);
|
||||||
|
@ -3142,7 +3131,6 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
|
||||||
vfe_dev = update_vfes[i];
|
vfe_dev = update_vfes[i];
|
||||||
if (!vfe_dev)
|
if (!vfe_dev)
|
||||||
continue;
|
continue;
|
||||||
msm_isp_update_stream_bandwidth(vfe_dev);
|
|
||||||
vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
|
vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
|
||||||
vfe_dev->vfe_base, wm_reload_mask[i]);
|
vfe_dev->vfe_base, wm_reload_mask[i]);
|
||||||
|
|
||||||
|
|
|
@ -2339,6 +2339,7 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||||
{
|
{
|
||||||
long rc = 0;
|
long rc = 0;
|
||||||
int wm;
|
int wm;
|
||||||
|
int i;
|
||||||
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
|
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
|
||||||
ISP_DBG("%s E open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt);
|
ISP_DBG("%s E open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt);
|
||||||
mutex_lock(&vfe_dev->realtime_mutex);
|
mutex_lock(&vfe_dev->realtime_mutex);
|
||||||
|
@ -2388,6 +2389,8 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||||
msm_isp_end_avtimer();
|
msm_isp_end_avtimer();
|
||||||
vfe_dev->vt_enable = 0;
|
vfe_dev->vt_enable = 0;
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < VFE_SRC_MAX; i++)
|
||||||
|
vfe_dev->axi_data.src_info[i].lpm = 0;
|
||||||
MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
|
MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
|
||||||
vfe_dev->is_split = 0;
|
vfe_dev->is_split = 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue