Commit 112eee0c authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] omap3isp: Refactor modules stop failure handling

Modules failing to stop are fatal errors for the preview engine only.
Flag that condition separately from the other stop failures to prepare
support for more fatal errors.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarSakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 661112cb
......@@ -873,15 +873,12 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe,
unsigned long flags;
int ret;
/* If the preview engine crashed it might not respond to read/write
* operations on the L4 bus. This would result in a bus fault and a
* kernel oops. Refuse to start streaming in that case. This check must
* be performed before the loop below to avoid starting entities if the
* pipeline won't start anyway (those entities would then likely fail to
* stop, making the problem worse).
/* Refuse to start streaming if an entity included in the pipeline has
* crashed. This check must be performed before the loop below to avoid
* starting entities if the pipeline won't start anyway (those entities
* would then likely fail to stop, making the problem worse).
*/
if ((pipe->entities & isp->crashed) &
(1U << isp->isp_prev.subdev.entity.id))
if (pipe->entities & isp->crashed)
return -EIO;
spin_lock_irqsave(&pipe->lock, flags);
......@@ -1014,13 +1011,23 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
else
ret = 0;
/* Handle stop failures. An entity that fails to stop can
* usually just be restarted. Flag the stop failure nonetheless
* to trigger an ISP reset the next time the device is released,
* just in case.
*
* The preview engine is a special case. A failure to stop can
* mean a hardware crash. When that happens the preview engine
* won't respond to read/write operations on the L4 bus anymore,
* resulting in a bus fault and a kernel oops next time it gets
* accessed. Mark it as crashed to prevent pipelines including
* it from being started.
*/
if (ret) {
dev_info(isp->dev, "Unable to stop %s\n", subdev->name);
/* If the entity failed to stopped, assume it has
* crashed. Mark it as such, the ISP will be reset when
* applications will release it.
*/
isp->crashed |= 1U << subdev->entity.id;
isp->stop_failure = true;
if (subdev == &isp->isp_prev.subdev)
isp->crashed |= 1U << subdev->entity.id;
failure = -ETIMEDOUT;
}
}
......@@ -1225,6 +1232,7 @@ static int isp_reset(struct isp_device *isp)
udelay(1);
}
isp->stop_failure = false;
isp->crashed = 0;
return 0;
}
......@@ -1636,7 +1644,7 @@ void omap3isp_put(struct isp_device *isp)
/* Reset the ISP if an entity has failed to stop. This is the
* only way to recover from such conditions.
*/
if (isp->crashed)
if (isp->crashed || isp->stop_failure)
isp_reset(isp);
isp_disable_clocks(isp);
}
......
......@@ -154,6 +154,7 @@ struct isp_xclk {
* regions.
* @stat_lock: Spinlock for handling statistics
* @isp_mutex: Mutex for serializing requests to ISP.
* @stop_failure: Indicates that an entity failed to stop.
* @crashed: Bitmask of crashed entities (indexed by entity ID)
* @has_context: Context has been saved at least once and can be restored.
* @ref_count: Reference count for handling multiple ISP requests.
......@@ -191,6 +192,7 @@ struct isp_device {
/* ISP Obj */
spinlock_t stat_lock; /* common lock for statistic drivers */
struct mutex isp_mutex; /* For handling ref_count field */
bool stop_failure;
u32 crashed;
int has_context;
int ref_count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment