|
|
@@ -605,7 +605,10 @@ static void free_vbs(struct vpe_ctx *ctx)
|
|
|
spin_lock_irqsave(&dev->lock, flags);
|
|
|
if (ctx->src_vbs[2]) {
|
|
|
v4l2_m2m_buf_done(ctx->src_vbs[2], VB2_BUF_STATE_DONE);
|
|
|
- v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_DONE);
|
|
|
+ if (ctx->src_vbs[1] && (ctx->src_vbs[1] != ctx->src_vbs[2]))
|
|
|
+ v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_DONE);
|
|
|
+ ctx->src_vbs[2] = NULL;
|
|
|
+ ctx->src_vbs[1] = NULL;
|
|
|
}
|
|
|
spin_unlock_irqrestore(&dev->lock, flags);
|
|
|
}
|
|
|
@@ -1443,6 +1446,14 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data)
|
|
|
ctx->src_vbs[1] = ctx->src_vbs[0];
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Since the vb2_buf_done has already been called fir therse
|
|
|
+ * buffer we can now NULL them out so that we won't try
|
|
|
+ * to clean out stray pointer later on.
|
|
|
+ */
|
|
|
+ ctx->src_vbs[0] = NULL;
|
|
|
+ ctx->dst_vb = NULL;
|
|
|
+
|
|
|
ctx->bufs_completed++;
|
|
|
if (ctx->bufs_completed < ctx->bufs_per_job && job_ready(ctx)) {
|
|
|
device_run(ctx);
|
|
|
@@ -2027,9 +2038,57 @@ static int vpe_start_streaming(struct vb2_queue *q, unsigned int count)
|
|
|
static void vpe_stop_streaming(struct vb2_queue *q)
|
|
|
{
|
|
|
struct vpe_ctx *ctx = vb2_get_drv_priv(q);
|
|
|
+ struct vb2_v4l2_buffer *vb;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
vpe_dump_regs(ctx->dev);
|
|
|
vpdma_dump_regs(ctx->dev->vpdma);
|
|
|
+
|
|
|
+ for (;;) {
|
|
|
+ if (V4L2_TYPE_IS_OUTPUT(q->type))
|
|
|
+ vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
|
|
|
+ else
|
|
|
+ vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
|
|
|
+ if (!vb)
|
|
|
+ break;
|
|
|
+ spin_lock_irqsave(&ctx->dev->lock, flags);
|
|
|
+ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
|
|
|
+ spin_unlock_irqrestore(&ctx->dev->lock, flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Cleanup the in-transit vb2 buffers that have been
|
|
|
+ * removed from their respective queue already but for
|
|
|
+ * which procecessing has not been completed yet.
|
|
|
+ */
|
|
|
+ if (V4L2_TYPE_IS_OUTPUT(q->type)) {
|
|
|
+ spin_lock_irqsave(&ctx->dev->lock, flags);
|
|
|
+
|
|
|
+ if (ctx->src_vbs[2])
|
|
|
+ v4l2_m2m_buf_done(ctx->src_vbs[2], VB2_BUF_STATE_ERROR);
|
|
|
+
|
|
|
+ if (ctx->src_vbs[1] && (ctx->src_vbs[1] != ctx->src_vbs[2]))
|
|
|
+ v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_ERROR);
|
|
|
+
|
|
|
+ if (ctx->src_vbs[0] &&
|
|
|
+ (ctx->src_vbs[0] != ctx->src_vbs[1]) &&
|
|
|
+ (ctx->src_vbs[0] != ctx->src_vbs[2]))
|
|
|
+ v4l2_m2m_buf_done(ctx->src_vbs[0], VB2_BUF_STATE_ERROR);
|
|
|
+
|
|
|
+ ctx->src_vbs[2] = NULL;
|
|
|
+ ctx->src_vbs[1] = NULL;
|
|
|
+ ctx->src_vbs[0] = NULL;
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&ctx->dev->lock, flags);
|
|
|
+ } else {
|
|
|
+ if (ctx->dst_vb) {
|
|
|
+ spin_lock_irqsave(&ctx->dev->lock, flags);
|
|
|
+
|
|
|
+ v4l2_m2m_buf_done(ctx->dst_vb, VB2_BUF_STATE_ERROR);
|
|
|
+ ctx->dst_vb = NULL;
|
|
|
+ spin_unlock_irqrestore(&ctx->dev->lock, flags);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static const struct vb2_ops vpe_qops = {
|
|
|
@@ -2222,7 +2281,6 @@ static int vpe_release(struct file *file)
|
|
|
vpe_dbg(dev, "releasing instance %p\n", ctx);
|
|
|
|
|
|
mutex_lock(&dev->dev_mutex);
|
|
|
- free_vbs(ctx);
|
|
|
free_mv_buffers(ctx);
|
|
|
vpdma_free_desc_list(&ctx->desc_list);
|
|
|
vpdma_free_desc_buf(&ctx->mmr_adb);
|