aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/omap3isp/isp.c27
-rw-r--r--drivers/media/video/omap3isp/isp.h3
-rw-r--r--drivers/media/video/omap3isp/ispvideo.c4
-rw-r--r--drivers/media/video/omap3isp/ispvideo.h2
4 files changed, 29 insertions, 7 deletions
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c
index 12d5f923e1d0..3db8583497ee 100644
--- a/drivers/media/video/omap3isp/isp.c
+++ b/drivers/media/video/omap3isp/isp.c
@@ -739,6 +739,17 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
739 unsigned long flags; 739 unsigned long flags;
740 int ret; 740 int ret;
741 741
742 /* If the preview engine crashed it might not respond to read/write
743 * operations on the L4 bus. This would result in a bus fault and a
744 * kernel oops. Refuse to start streaming in that case. This check must
745 * be performed before the loop below to avoid starting entities if the
746 * pipeline won't start anyway (those entities would then likely fail to
747 * stop, making the problem worse).
748 */
749 if ((pipe->entities & isp->crashed) &
750 (1U << isp->isp_prev.subdev.entity.id))
751 return -EIO;
752
742 spin_lock_irqsave(&pipe->lock, flags); 753 spin_lock_irqsave(&pipe->lock, flags);
743 pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT); 754 pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
744 spin_unlock_irqrestore(&pipe->lock, flags); 755 spin_unlock_irqrestore(&pipe->lock, flags);
@@ -879,13 +890,15 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
879 890
880 if (ret) { 891 if (ret) {
881 dev_info(isp->dev, "Unable to stop %s\n", subdev->name); 892 dev_info(isp->dev, "Unable to stop %s\n", subdev->name);
893 /* If the entity failed to stopped, assume it has
894 * crashed. Mark it as such, the ISP will be reset when
895 * applications will release it.
896 */
897 isp->crashed |= 1U << subdev->entity.id;
882 failure = -ETIMEDOUT; 898 failure = -ETIMEDOUT;
883 } 899 }
884 } 900 }
885 901
886 if (failure < 0)
887 isp->needs_reset = true;
888
889 return failure; 902 return failure;
890} 903}
891 904
@@ -1069,6 +1082,7 @@ static int isp_reset(struct isp_device *isp)
1069 udelay(1); 1082 udelay(1);
1070 } 1083 }
1071 1084
1085 isp->crashed = 0;
1072 return 0; 1086 return 0;
1073} 1087}
1074 1088
@@ -1496,10 +1510,11 @@ void omap3isp_put(struct isp_device *isp)
1496 if (--isp->ref_count == 0) { 1510 if (--isp->ref_count == 0) {
1497 isp_disable_interrupts(isp); 1511 isp_disable_interrupts(isp);
1498 isp_save_ctx(isp); 1512 isp_save_ctx(isp);
1499 if (isp->needs_reset) { 1513 /* Reset the ISP if an entity has failed to stop. This is the
1514 * only way to recover from such conditions.
1515 */
1516 if (isp->crashed)
1500 isp_reset(isp); 1517 isp_reset(isp);
1501 isp->needs_reset = false;
1502 }
1503 isp_disable_clocks(isp); 1518 isp_disable_clocks(isp);
1504 } 1519 }
1505 mutex_unlock(&isp->isp_mutex); 1520 mutex_unlock(&isp->isp_mutex);
diff --git a/drivers/media/video/omap3isp/isp.h b/drivers/media/video/omap3isp/isp.h
index d96603eb0d17..f8d1f100fc19 100644
--- a/drivers/media/video/omap3isp/isp.h
+++ b/drivers/media/video/omap3isp/isp.h
@@ -145,6 +145,7 @@ struct isp_platform_callback {
145 * @raw_dmamask: Raw DMA mask 145 * @raw_dmamask: Raw DMA mask
146 * @stat_lock: Spinlock for handling statistics 146 * @stat_lock: Spinlock for handling statistics
147 * @isp_mutex: Mutex for serializing requests to ISP. 147 * @isp_mutex: Mutex for serializing requests to ISP.
148 * @crashed: Bitmask of crashed entities (indexed by entity ID)
148 * @has_context: Context has been saved at least once and can be restored. 149 * @has_context: Context has been saved at least once and can be restored.
149 * @ref_count: Reference count for handling multiple ISP requests. 150 * @ref_count: Reference count for handling multiple ISP requests.
150 * @cam_ick: Pointer to camera interface clock structure. 151 * @cam_ick: Pointer to camera interface clock structure.
@@ -184,7 +185,7 @@ struct isp_device {
184 /* ISP Obj */ 185 /* ISP Obj */
185 spinlock_t stat_lock; /* common lock for statistic drivers */ 186 spinlock_t stat_lock; /* common lock for statistic drivers */
186 struct mutex isp_mutex; /* For handling ref_count field */ 187 struct mutex isp_mutex; /* For handling ref_count field */
187 bool needs_reset; 188 u32 crashed;
188 int has_context; 189 int has_context;
189 int ref_count; 190 int ref_count;
190 unsigned int autoidle; 191 unsigned int autoidle;
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c
index b02070057724..2107d99d523a 100644
--- a/drivers/media/video/omap3isp/ispvideo.c
+++ b/drivers/media/video/omap3isp/ispvideo.c
@@ -292,6 +292,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
292 int ret; 292 int ret;
293 293
294 pipe->max_rate = pipe->l3_ick; 294 pipe->max_rate = pipe->l3_ick;
295 pipe->entities = 0;
295 296
296 subdev = isp_video_remote_subdev(pipe->output, NULL); 297 subdev = isp_video_remote_subdev(pipe->output, NULL);
297 if (subdev == NULL) 298 if (subdev == NULL)
@@ -299,6 +300,9 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
299 300
300 while (1) { 301 while (1) {
301 unsigned int shifter_link; 302 unsigned int shifter_link;
303
304 pipe->entities |= 1U << subdev->entity.id;
305
302 /* Retrieve the sink format */ 306 /* Retrieve the sink format */
303 pad = &subdev->entity.pads[0]; 307 pad = &subdev->entity.pads[0];
304 if (!(pad->flags & MEDIA_PAD_FL_SINK)) 308 if (!(pad->flags & MEDIA_PAD_FL_SINK))
diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/video/omap3isp/ispvideo.h
index d91bdb919be0..c9187cbc3557 100644
--- a/drivers/media/video/omap3isp/ispvideo.h
+++ b/drivers/media/video/omap3isp/ispvideo.h
@@ -88,6 +88,7 @@ enum isp_pipeline_state {
88/* 88/*
89 * struct isp_pipeline - An ISP hardware pipeline 89 * struct isp_pipeline - An ISP hardware pipeline
90 * @error: A hardware error occurred during capture 90 * @error: A hardware error occurred during capture
91 * @entities: Bitmask of entities in the pipeline (indexed by entity ID)
91 */ 92 */
92struct isp_pipeline { 93struct isp_pipeline {
93 struct media_pipeline pipe; 94 struct media_pipeline pipe;
@@ -96,6 +97,7 @@ struct isp_pipeline {
96 enum isp_pipeline_stream_state stream_state; 97 enum isp_pipeline_stream_state stream_state;
97 struct isp_video *input; 98 struct isp_video *input;
98 struct isp_video *output; 99 struct isp_video *output;
100 u32 entities;
99 unsigned long l3_ick; 101 unsigned long l3_ick;
100 unsigned int max_rate; 102 unsigned int max_rate;
101 atomic_t frame_number; 103 atomic_t frame_number;