static void isp_isr_sbl(struct isp_device *isp)
 {
        struct device *dev = isp->dev;
+       struct isp_pipeline *pipe;
        u32 sbl_pcr;
 
        /*
        if (sbl_pcr)
                dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
 
-       if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF
-                    | ISPSBL_PCR_CSIB_WBL_OVF)) {
-               isp->isp_ccdc.error = 1;
-               if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
-                       isp->isp_prev.error = 1;
-               if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
-                       isp->isp_res.error = 1;
+       if (sbl_pcr & ISPSBL_PCR_CSIB_WBL_OVF) {
+               pipe = to_isp_pipeline(&isp->isp_ccp2.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
+       }
+
+       if (sbl_pcr & ISPSBL_PCR_CSIA_WBL_OVF) {
+               pipe = to_isp_pipeline(&isp->isp_csi2a.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
+       }
+
+       if (sbl_pcr & ISPSBL_PCR_CCDC_WBL_OVF) {
+               pipe = to_isp_pipeline(&isp->isp_ccdc.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
        }
 
        if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
-               isp->isp_prev.error = 1;
-               if (isp->isp_res.input == RESIZER_INPUT_VP &&
-                   !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER))
-                       isp->isp_res.error = 1;
+               pipe = to_isp_pipeline(&isp->isp_prev.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
        }
 
        if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
                       | ISPSBL_PCR_RSZ2_WBL_OVF
                       | ISPSBL_PCR_RSZ3_WBL_OVF
-                      | ISPSBL_PCR_RSZ4_WBL_OVF))
-               isp->isp_res.error = 1;
+                      | ISPSBL_PCR_RSZ4_WBL_OVF)) {
+               pipe = to_isp_pipeline(&isp->isp_res.subdev.entity);
+               if (pipe != NULL)
+                       pipe->error = true;
+       }
 
        if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
                omap3isp_stat_sbl_overflow(&isp->isp_af);
                                       IRQ0STATUS_HS_VS_IRQ;
        struct isp_device *isp = _isp;
        u32 irqstatus;
-       int ret;
 
        irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
        isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
 
        isp_isr_sbl(isp);
 
-       if (irqstatus & IRQ0STATUS_CSIA_IRQ) {
-               ret = omap3isp_csi2_isr(&isp->isp_csi2a);
-               if (ret)
-                       isp->isp_ccdc.error = 1;
-       }
+       if (irqstatus & IRQ0STATUS_CSIA_IRQ)
+               omap3isp_csi2_isr(&isp->isp_csi2a);
 
-       if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
-               ret = omap3isp_ccp2_isr(&isp->isp_ccp2);
-               if (ret)
-                       isp->isp_ccdc.error = 1;
-       }
+       if (irqstatus & IRQ0STATUS_CSIB_IRQ)
+               omap3isp_ccp2_isr(&isp->isp_ccp2);
 
        if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
                if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
 
        unsigned long flags;
 
        if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
+               struct isp_pipeline *pipe =
+                       to_isp_pipeline(&ccdc->subdev.entity);
+
                ccdc_lsc_error_handler(ccdc);
-               ccdc->error = 1;
+               pipe->error = true;
                dev_dbg(to_device(ccdc), "lsc prefetch error\n");
        }
 
                goto done;
        }
 
-       buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error);
+       buffer = omap3isp_video_buffer_next(&ccdc->video_out);
        if (buffer != NULL) {
                ccdc_set_outaddr(ccdc, buffer->isp_addr);
                restart = 1;
                                        ISP_PIPELINE_STREAM_SINGLESHOT);
 
 done:
-       ccdc->error = 0;
        return restart;
 }
 
                 */
                ccdc_config_vp(ccdc);
                ccdc_enable_vp(ccdc, 1);
-               ccdc->error = 0;
                ccdc_print_status(ccdc);
        }
 
 
  * @input: Active input
  * @output: Active outputs
  * @video_out: Output video node
- * @error: A hardware error occurred during capture
  * @alaw: A-law compression enabled (1) or disabled (0)
  * @lpf: Low pass filter enabled (1) or disabled (0)
  * @obclamp: Optical-black clamp enabled (1) or disabled (0)
        enum ccdc_input_entity input;
        unsigned int output;
        struct isp_video video_out;
-       unsigned int error;
 
        unsigned int alaw:1,
                     lpf:1,
 
        struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
        struct isp_buffer *buffer;
 
-       buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error);
+       buffer = omap3isp_video_buffer_next(&ccp2->video_in);
        if (buffer != NULL)
                ccp2_set_inaddr(ccp2, buffer->isp_addr);
 
                        omap3isp_pipeline_set_stream(pipe,
                                                ISP_PIPELINE_STREAM_SINGLESHOT);
        }
-
-       ccp2->error = 0;
 }
 
 /*
  * @ccp2: Pointer to ISP CCP2 device
  *
  * This will handle the CCP2 interrupts
- *
- * Returns -EIO in case of error, or 0 on success.
  */
-int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
+void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
 {
+       struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
        struct isp_device *isp = to_isp_device(ccp2);
-       int ret = 0;
        static const u32 ISPCCP2_LC01_ERROR =
                ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
                ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
                       ISPCCP2_LCM_IRQSTATUS);
        /* Errors */
        if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
-               ccp2->error = 1;
+               pipe->error = true;
                dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
-               return -EIO;
+               return;
        }
 
        if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
-               ccp2->error = 1;
+               pipe->error = true;
                dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
-               ret = -EIO;
        }
 
        if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
-               return 0;
+               return;
 
        /* Frame number propagation */
        if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) {
        /* Handle queued buffers on frame end interrupts */
        if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
                ccp2_isr_buffer(ccp2);
-
-       return ret;
 }
 
 /* -----------------------------------------------------------------------------
                if (enable == ISP_PIPELINE_STREAM_STOPPED)
                        return 0;
                atomic_set(&ccp2->stopping, 0);
-               ccp2->error = 0;
        }
 
        switch (enable) {
 
        struct isp_video video_in;
        struct isp_csiphy *phy;
        struct regulator *vdds_csib;
-       unsigned int error;
        enum isp_pipeline_stream_state state;
        wait_queue_head_t wait;
        atomic_t stopping;
 int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
                        struct v4l2_device *vdev);
 void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
-int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
+void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
 
 #endif /* OMAP3_ISP_CCP2_H */
 
 
        csi2_ctx_enable(isp, csi2, 0, 0);
 
-       buffer = omap3isp_video_buffer_next(&csi2->video_out, 0);
+       buffer = omap3isp_video_buffer_next(&csi2->video_out);
 
        /*
         * Let video queue operation restart engine if there is an underrun
 
 /*
  * omap3isp_csi2_isr - CSI2 interrupt handling.
- *
- * Return -EIO on Transmission error
  */
-int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
+void omap3isp_csi2_isr(struct isp_csi2_device *csi2)
 {
+       struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
        u32 csi2_irqstatus, cpxio1_irqstatus;
        struct isp_device *isp = csi2->isp;
-       int retval = 0;
 
        if (!csi2->available)
-               return -ENODEV;
+               return;
 
        csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
        isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
                               csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
                dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
                        "%x\n", cpxio1_irqstatus);
-               retval = -EIO;
+               pipe->error = true;
        }
 
        if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
                         ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
                        (csi2_irqstatus &
                         ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
-               retval = -EIO;
+               pipe->error = true;
        }
 
        if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
-               return 0;
+               return;
 
        /* Successful cases */
        if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
 
        if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
                dev_dbg(isp->dev, "CSI2: ECC correction done\n");
-
-       return retval;
 }
 
 /* -----------------------------------------------------------------------------
 
        atomic_t stopping;
 };
 
-int omap3isp_csi2_isr(struct isp_csi2_device *csi2);
+void omap3isp_csi2_isr(struct isp_csi2_device *csi2);
 int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
 int omap3isp_csi2_init(struct isp_device *isp);
 void omap3isp_csi2_cleanup(struct isp_device *isp);
 
        int restart = 0;
 
        if (prev->input == PREVIEW_INPUT_MEMORY) {
-               buffer = omap3isp_video_buffer_next(&prev->video_in,
-                                                   prev->error);
+               buffer = omap3isp_video_buffer_next(&prev->video_in);
                if (buffer != NULL)
                        preview_set_inaddr(prev, buffer->isp_addr);
                pipe->state |= ISP_PIPELINE_IDLE_INPUT;
        }
 
        if (prev->output & PREVIEW_OUTPUT_MEMORY) {
-               buffer = omap3isp_video_buffer_next(&prev->video_out,
-                                                   prev->error);
+               buffer = omap3isp_video_buffer_next(&prev->video_out);
                if (buffer != NULL) {
                        preview_set_outaddr(prev, buffer->isp_addr);
                        restart = 1;
        default:
                return;
        }
-
-       prev->error = 0;
 }
 
 /*
                omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
                preview_configure(prev);
                atomic_set(&prev->stopping, 0);
-               prev->error = 0;
                preview_print_status(prev);
        }
 
 
  * @output: Bitmask of the active output
  * @video_in: Input video entity
  * @video_out: Output video entity
- * @error: A hardware error occurred during capture
  * @params: Module configuration data
  * @shadow_update: If set, update the hardware configured in the next interrupt
  * @underrun: Whether the preview entity has queued buffers on the output
        unsigned int output;
        struct isp_video video_in;
        struct isp_video video_out;
-       unsigned int error;
 
        struct prev_params params;
        unsigned int shadow_update:1;
 
        /* Complete the output buffer and, if reading from memory, the input
         * buffer.
         */
-       buffer = omap3isp_video_buffer_next(&res->video_out, res->error);
+       buffer = omap3isp_video_buffer_next(&res->video_out);
        if (buffer != NULL) {
                resizer_set_outaddr(res, buffer->isp_addr);
                restart = 1;
        pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
 
        if (res->input == RESIZER_INPUT_MEMORY) {
-               buffer = omap3isp_video_buffer_next(&res->video_in, 0);
+               buffer = omap3isp_video_buffer_next(&res->video_in);
                if (buffer != NULL)
                        resizer_set_inaddr(res, buffer->isp_addr);
                pipe->state |= ISP_PIPELINE_IDLE_INPUT;
                if (restart)
                        resizer_enable_oneshot(res);
        }
-
-       res->error = 0;
 }
 
 /*
 
                omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
                resizer_configure(res);
-               res->error = 0;
                resizer_print_status(res);
        }
 
 
        enum resizer_input_entity input;
        struct isp_video video_in;
        struct isp_video video_out;
-       unsigned int error;
 
        u32 addr_base;   /* stored source buffer address in memory mode */
        u32 crop_offset; /* additional offset for crop in memory mode */
 
 /*
  * omap3isp_video_buffer_next - Complete the current buffer and return the next
  * @video: ISP video object
- * @error: Whether an error occurred during capture
  *
  * Remove the current video buffer from the DMA queue and fill its timestamp,
  * field count and state fields before waking up its completion handler.
  *
- * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0)
- * or VIDEOBUF_ERROR otherwise (@error is non-zero).
+ * For capture video nodes the buffer state is set to ISP_BUF_STATE_DONE if no
+ * error has been flagged in the pipeline, or to ISP_BUF_STATE_ERROR otherwise.
+ * For video output nodes the buffer state is always set to ISP_BUF_STATE_DONE.
  *
  * The DMA queue is expected to contain at least one buffer.
  *
  * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
  * empty.
  */
-struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
-                                             unsigned int error)
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 {
        struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
        struct isp_video_queue *queue = video->queue;
        else
                buf->vbuf.sequence = atomic_read(&pipe->frame_number);
 
-       buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE;
+       /* Report pipeline errors to userspace on the capture device side. */
+       if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
+               buf->state = ISP_BUF_STATE_ERROR;
+               pipe->error = false;
+       } else {
+               buf->state = ISP_BUF_STATE_DONE;
+       }
 
        wake_up(&buf->wait);
 
        if (ret < 0)
                goto error;
 
+       pipe->error = false;
+
        spin_lock_irqsave(&pipe->lock, flags);
        pipe->state &= ~ISP_PIPELINE_STREAM;
        pipe->state |= state;
 
        ISP_PIPELINE_STREAM = 64,
 };
 
+/*
+ * struct isp_pipeline - An ISP hardware pipeline
+ * @error: A hardware error occurred during capture
+ */
 struct isp_pipeline {
        struct media_pipeline pipe;
        spinlock_t lock;                /* Pipeline state and queue flags */
        unsigned int max_rate;
        atomic_t frame_number;
        bool do_propagation; /* of frame number */
+       bool error;
        struct v4l2_fract max_timeperframe;
 };
 
 int omap3isp_video_register(struct isp_video *video,
                            struct v4l2_device *vdev);
 void omap3isp_video_unregister(struct isp_video *video);
-struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
-                                             unsigned int error);
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video);
 void omap3isp_video_resume(struct isp_video *video, int continuous);
 struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);