aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaik Ameer Basha <shaik.ameer@samsung.com>2013-09-20 02:26:17 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-10-28 13:21:58 -0400
commitd9315160ed4dc76f6f01acb1b05e92e2a891b9bb (patch)
treeba749519ec9c3788ae1b8f58fe2ed4dc6fc5ff50
parent84e680980917df60210af713e39400752dc4763d (diff)
[media] exynos-gsc: Handle ctx job finish when aborted
When the current context is running, 1] If release() or streamoff() is called on the current context, it waits until the job is aborted or finished. 2] If the job is finished, driver will call the v4l2_m2m_job_finish(). 3] If the job is aborted inside device_run callback, then driver has to inform the v4l2 mem2mem framework about the same by calling v4l2_m2m_job_finish() with VB2_BUF_STATE_ERROR. The current code doesn't call v4l2_m2m_job_finish() in the case, where the job is aborted from the device_run callback. This scenerio is producing a hang as the other queued contexts are not getting scheduled. By adding the ABORT state, driver can understand the current job is aborted and not finished. By checking this flag, driver can call v4l2_m2m_job_finish() with VB2_BUF_STATE_ERROR. Signed-off-by: Shaik Ameer Basha <shaik.ameer@samsung.com> Signed-off-by: Avnd Kiran <avnd.kiran@samsung.com> Signed-off-by: Kamil Debski <k.debski@samsung.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-core.h1
-rw-r--r--drivers/media/platform/exynos-gsc/gsc-m2m.c29
2 files changed, 17 insertions, 13 deletions
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index 76435d3bf62d..ef0a6564cef9 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -45,6 +45,7 @@
45#define GSC_DST_FMT (1 << 2) 45#define GSC_DST_FMT (1 << 2)
46#define GSC_CTX_M2M (1 << 3) 46#define GSC_CTX_M2M (1 << 3)
47#define GSC_CTX_STOP_REQ (1 << 6) 47#define GSC_CTX_STOP_REQ (1 << 6)
48#define GSC_CTX_ABORT (1 << 7)
48 49
49enum gsc_dev_flags { 50enum gsc_dev_flags {
50 /* for global */ 51 /* for global */
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index e576ff2de3de..810c3e13970c 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -46,6 +46,17 @@ static int gsc_m2m_ctx_stop_req(struct gsc_ctx *ctx)
46 return ret == 0 ? -ETIMEDOUT : ret; 46 return ret == 0 ? -ETIMEDOUT : ret;
47} 47}
48 48
49static void __gsc_m2m_job_abort(struct gsc_ctx *ctx)
50{
51 int ret;
52
53 ret = gsc_m2m_ctx_stop_req(ctx);
54 if ((ret == -ETIMEDOUT) || (ctx->state & GSC_CTX_ABORT)) {
55 gsc_ctx_state_lock_clear(GSC_CTX_STOP_REQ | GSC_CTX_ABORT, ctx);
56 gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
57 }
58}
59
49static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count) 60static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
50{ 61{
51 struct gsc_ctx *ctx = q->drv_priv; 62 struct gsc_ctx *ctx = q->drv_priv;
@@ -58,11 +69,8 @@ static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
58static int gsc_m2m_stop_streaming(struct vb2_queue *q) 69static int gsc_m2m_stop_streaming(struct vb2_queue *q)
59{ 70{
60 struct gsc_ctx *ctx = q->drv_priv; 71 struct gsc_ctx *ctx = q->drv_priv;
61 int ret;
62 72
63 ret = gsc_m2m_ctx_stop_req(ctx); 73 __gsc_m2m_job_abort(ctx);
64 if (ret == -ETIMEDOUT)
65 gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
66 74
67 pm_runtime_put(&ctx->gsc_dev->pdev->dev); 75 pm_runtime_put(&ctx->gsc_dev->pdev->dev);
68 76
@@ -91,15 +99,9 @@ void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state)
91 } 99 }
92} 100}
93 101
94
95static void gsc_m2m_job_abort(void *priv) 102static void gsc_m2m_job_abort(void *priv)
96{ 103{
97 struct gsc_ctx *ctx = priv; 104 __gsc_m2m_job_abort((struct gsc_ctx *)priv);
98 int ret;
99
100 ret = gsc_m2m_ctx_stop_req(ctx);
101 if (ret == -ETIMEDOUT)
102 gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
103} 105}
104 106
105static int gsc_get_bufs(struct gsc_ctx *ctx) 107static int gsc_get_bufs(struct gsc_ctx *ctx)
@@ -150,9 +152,10 @@ static void gsc_m2m_device_run(void *priv)
150 gsc->m2m.ctx = ctx; 152 gsc->m2m.ctx = ctx;
151 } 153 }
152 154
153 is_set = (ctx->state & GSC_CTX_STOP_REQ) ? 1 : 0; 155 is_set = ctx->state & GSC_CTX_STOP_REQ;
154 ctx->state &= ~GSC_CTX_STOP_REQ;
155 if (is_set) { 156 if (is_set) {
157 ctx->state &= ~GSC_CTX_STOP_REQ;
158 ctx->state |= GSC_CTX_ABORT;
156 wake_up(&gsc->irq_queue); 159 wake_up(&gsc->irq_queue);
157 goto put_device; 160 goto put_device;
158 } 161 }