]> Pileus Git - ~andy/linux/commitdiff
[media] omap3isp: Refactor modules stop failure handling
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Mon, 16 Dec 2013 02:49:42 +0000 (23:49 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Tue, 7 Jan 2014 10:09:15 +0000 (08:09 -0200)
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: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/isp.h

index 7e09c1dd137a0c16e915ba3c1b37dd0b73d3a76f..5807185262fef29a20dbb2cd5380da6887b182b7 100644 (file)
@@ -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);
        }
index 5b91f86198865f43d19466425451ad2dce143842..081f5ec5a663c014e1ab270d463ed9b6e63efee0 100644 (file)
@@ -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;