diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2011-02-23 08:24:33 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-22 04:54:15 -0300 |
commit | 4ecbf5d1d2bb7d1e3882de79e512c1a0a2816581 (patch) | |
tree | 42270272224cdc3532f0923a8317adfecd0d6dcc /drivers/media/video/s5p-fimc/fimc-core.h | |
parent | a0f8caefaf3295721ef00415c7d63ec10af253ab (diff) |
[media] s5p-fimc: Prevent hanging on device close and fix the locking
Rework the locking in m2m driver to assure proper operation on SMP systems.
When job_abort or stop_streaming was called to immediately shutdown
a memory-to-memory transaction video buffers scheduled for processing
were never returned to vb2 and v4l2_m2m_job_finish was not called
which led to hanging.
Correct this and also return the unprocessed buffers to vb2 marking
them as erroneous, in case the end of frame interrupt do not occur.
Reported-by: Sewoon Park <seuni.park@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-core.h')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-core.h | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index 4829a2515076..41b135249d1f 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -14,6 +14,7 @@ /*#define DEBUG*/ #include <linux/sched.h> +#include <linux/spinlock.h> #include <linux/types.h> #include <linux/videodev2.h> #include <linux/io.h> @@ -57,7 +58,6 @@ enum fimc_dev_flags { ST_IDLE, ST_OUTDMA_RUN, ST_M2M_PEND, - ST_M2M_SHUT, /* for capture node */ ST_CAPT_PEND, ST_CAPT_RUN, @@ -71,13 +71,6 @@ enum fimc_dev_flags { #define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state) #define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state) -#define fimc_capture_active(dev) \ - (test_bit(ST_CAPT_RUN, &(dev)->state) || \ - test_bit(ST_CAPT_PEND, &(dev)->state)) - -#define fimc_capture_streaming(dev) \ - test_bit(ST_CAPT_STREAM, &(dev)->state) - enum fimc_datapath { FIMC_CAMERA, FIMC_DMA, @@ -119,6 +112,7 @@ enum fimc_color_fmt { #define FIMC_DST_FMT (1 << 4) #define FIMC_CTX_M2M (1 << 5) #define FIMC_CTX_CAP (1 << 6) +#define FIMC_CTX_SHUT (1 << 7) /* Image conversion flags */ #define FIMC_IN_DMA_ACCESS_TILED (1 << 0) @@ -476,6 +470,38 @@ struct fimc_ctx { struct v4l2_m2m_ctx *m2m_ctx; }; +static inline bool fimc_capture_active(struct fimc_dev *fimc) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&fimc->slock, flags); + ret = !!(fimc->state & (1 << ST_CAPT_RUN) || + fimc->state & (1 << ST_CAPT_PEND)); + spin_unlock_irqrestore(&fimc->slock, flags); + return ret; +} + +static inline void fimc_ctx_state_lock_set(u32 state, struct fimc_ctx *ctx) +{ + unsigned long flags; + + spin_lock_irqsave(&ctx->slock, flags); + ctx->state |= state; + spin_unlock_irqrestore(&ctx->slock, flags); +} + +static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx) +{ + unsigned long flags; + bool ret; + + spin_lock_irqsave(&ctx->slock, flags); + ret = (ctx->state & mask) == mask; + spin_unlock_irqrestore(&ctx->slock, flags); + return ret; +} + static inline int tiled_fmt(struct fimc_fmt *fmt) { return fmt->fourcc == V4L2_PIX_FMT_NV12MT; @@ -535,7 +561,7 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, struct fimc_frame *frame; if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) { - if (ctx->state & FIMC_CTX_M2M) + if (fimc_ctx_state_is_set(FIMC_CTX_M2M, ctx)) frame = &ctx->s_frame; else return ERR_PTR(-EINVAL); |