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).
+        */
+       if ((pipe->entities & isp->crashed) &
+           (1U << isp->isp_prev.subdev.entity.id))
+               return -EIO;
+
        spin_lock_irqsave(&pipe->lock, flags);
        pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
        spin_unlock_irqrestore(&pipe->lock, flags);
 
                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;
                        failure = -ETIMEDOUT;
                }
        }
 
-       if (failure < 0)
-               isp->needs_reset = true;
-
        return failure;
 }
 
                udelay(1);
        }
 
+       isp->crashed = 0;
        return 0;
 }
 
        if (--isp->ref_count == 0) {
                isp_disable_interrupts(isp);
                isp_save_ctx(isp);
-               if (isp->needs_reset) {
+               /* Reset the ISP if an entity has failed to stop. This is the
+                * only way to recover from such conditions.
+                */
+               if (isp->crashed)
                        isp_reset(isp);
-                       isp->needs_reset = false;
-               }
                isp_disable_clocks(isp);
        }
        mutex_unlock(&isp->isp_mutex);
 
  * @raw_dmamask: Raw DMA mask
  * @stat_lock: Spinlock for handling statistics
  * @isp_mutex: Mutex for serializing requests to ISP.
+ * @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.
  * @cam_ick: Pointer to camera interface clock structure.
        /* ISP Obj */
        spinlock_t stat_lock;   /* common lock for statistic drivers */
        struct mutex isp_mutex; /* For handling ref_count field */
-       bool needs_reset;
+       u32 crashed;
        int has_context;
        int ref_count;
        unsigned int autoidle;
 
        int ret;
 
        pipe->max_rate = pipe->l3_ick;
+       pipe->entities = 0;
 
        subdev = isp_video_remote_subdev(pipe->output, NULL);
        if (subdev == NULL)
 
        while (1) {
                unsigned int shifter_link;
+
+               pipe->entities |= 1U << subdev->entity.id;
+
                /* Retrieve the sink format */
                pad = &subdev->entity.pads[0];
                if (!(pad->flags & MEDIA_PAD_FL_SINK))
 
 /*
  * struct isp_pipeline - An ISP hardware pipeline
  * @error: A hardware error occurred during capture
+ * @entities: Bitmask of entities in the pipeline (indexed by entity ID)
  */
 struct isp_pipeline {
        struct media_pipeline pipe;
        enum isp_pipeline_stream_state stream_state;
        struct isp_video *input;
        struct isp_video *output;
+       u32 entities;
        unsigned long l3_ick;
        unsigned int max_rate;
        atomic_t frame_number;