aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/omap3isp/isp.c36
-rw-r--r--drivers/media/platform/omap3isp/isp.h2
2 files changed, 24 insertions, 14 deletions
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 7e09c1dd137a..5807185262fe 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -873,15 +873,12 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
873 unsigned long flags; 873 unsigned long flags;
874 int ret; 874 int ret;
875 875
876 /* If the preview engine crashed it might not respond to read/write 876 /* Refuse to start streaming if an entity included in the pipeline has
877 * operations on the L4 bus. This would result in a bus fault and a 877 * crashed. This check must be performed before the loop below to avoid
878 * kernel oops. Refuse to start streaming in that case. This check must 878 * starting entities if the pipeline won't start anyway (those entities
879 * be performed before the loop below to avoid starting entities if the 879 * would then likely fail to stop, making the problem worse).
880 * pipeline won't start anyway (those entities would then likely fail to
881 * stop, making the problem worse).
882 */ 880 */
883 if ((pipe->entities & isp->crashed) & 881 if (pipe->entities & isp->crashed)
884 (1U << isp->isp_prev.subdev.entity.id))
885 return -EIO; 882 return -EIO;
886 883
887 spin_lock_irqsave(&pipe->lock, flags); 884 spin_lock_irqsave(&pipe->lock, flags);
@@ -1014,13 +1011,23 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
1014 else 1011 else
1015 ret = 0; 1012 ret = 0;
1016 1013
1014 /* Handle stop failures. An entity that fails to stop can
1015 * usually just be restarted. Flag the stop failure nonetheless
1016 * to trigger an ISP reset the next time the device is released,
1017 * just in case.
1018 *
1019 * The preview engine is a special case. A failure to stop can
1020 * mean a hardware crash. When that happens the preview engine
1021 * won't respond to read/write operations on the L4 bus anymore,
1022 * resulting in a bus fault and a kernel oops next time it gets
1023 * accessed. Mark it as crashed to prevent pipelines including
1024 * it from being started.
1025 */
1017 if (ret) { 1026 if (ret) {
1018 dev_info(isp->dev, "Unable to stop %s\n", subdev->name); 1027 dev_info(isp->dev, "Unable to stop %s\n", subdev->name);
1019 /* If the entity failed to stopped, assume it has 1028 isp->stop_failure = true;
1020 * crashed. Mark it as such, the ISP will be reset when 1029 if (subdev == &isp->isp_prev.subdev)
1021 * applications will release it. 1030 isp->crashed |= 1U << subdev->entity.id;
1022 */
1023 isp->crashed |= 1U << subdev->entity.id;
1024 failure = -ETIMEDOUT; 1031 failure = -ETIMEDOUT;
1025 } 1032 }
1026 } 1033 }
@@ -1225,6 +1232,7 @@ static int isp_reset(struct isp_device *isp)
1225 udelay(1); 1232 udelay(1);
1226 } 1233 }
1227 1234
1235 isp->stop_failure = false;
1228 isp->crashed = 0; 1236 isp->crashed = 0;
1229 return 0; 1237 return 0;
1230} 1238}
@@ -1636,7 +1644,7 @@ void omap3isp_put(struct isp_device *isp)
1636 /* Reset the ISP if an entity has failed to stop. This is the 1644 /* Reset the ISP if an entity has failed to stop. This is the
1637 * only way to recover from such conditions. 1645 * only way to recover from such conditions.
1638 */ 1646 */
1639 if (isp->crashed) 1647 if (isp->crashed || isp->stop_failure)
1640 isp_reset(isp); 1648 isp_reset(isp);
1641 isp_disable_clocks(isp); 1649 isp_disable_clocks(isp);
1642 } 1650 }
diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h
index 5b91f8619886..081f5ec5a663 100644
--- a/drivers/media/platform/omap3isp/isp.h
+++ b/drivers/media/platform/omap3isp/isp.h
@@ -154,6 +154,7 @@ struct isp_xclk {
154 * regions. 154 * regions.
155 * @stat_lock: Spinlock for handling statistics 155 * @stat_lock: Spinlock for handling statistics
156 * @isp_mutex: Mutex for serializing requests to ISP. 156 * @isp_mutex: Mutex for serializing requests to ISP.
157 * @stop_failure: Indicates that an entity failed to stop.
157 * @crashed: Bitmask of crashed entities (indexed by entity ID) 158 * @crashed: Bitmask of crashed entities (indexed by entity ID)
158 * @has_context: Context has been saved at least once and can be restored. 159 * @has_context: Context has been saved at least once and can be restored.
159 * @ref_count: Reference count for handling multiple ISP requests. 160 * @ref_count: Reference count for handling multiple ISP requests.
@@ -191,6 +192,7 @@ struct isp_device {
191 /* ISP Obj */ 192 /* ISP Obj */
192 spinlock_t stat_lock; /* common lock for statistic drivers */ 193 spinlock_t stat_lock; /* common lock for statistic drivers */
193 struct mutex isp_mutex; /* For handling ref_count field */ 194 struct mutex isp_mutex; /* For handling ref_count field */
195 bool stop_failure;
194 u32 crashed; 196 u32 crashed;
195 int has_context; 197 int has_context;
196 int ref_count; 198 int ref_count;