aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core/videobuf2-core.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2014-04-14 06:33:00 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-04-16 17:57:25 -0400
commit3415a89f48dce655ae353bc70a8e292764e8e931 (patch)
tree5e14b498a4f12817dce2ca2666aa05477ad0f755 /drivers/media/v4l2-core/videobuf2-core.c
parent5f26f2501b81190b60a0b72d611668fb6a59dd24 (diff)
[media] vb2: add thread support
In order to implement vb2 DVB support you need to be able to start a kernel thread that queues and dequeues buffers, calling a callback function for every buffer. This patch adds support for that. It's based on drivers/media/v4l2-core/videobuf-dvb.c, but with all the DVB specific stuff stripped out, thus making it much more generic. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/v4l2-core/videobuf2-core.c')
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 2075bac748c0..3f0cdb150dfd 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -6,6 +6,9 @@
6 * Author: Pawel Osciak <pawel@osciak.com> 6 * Author: Pawel Osciak <pawel@osciak.com>
7 * Marek Szyprowski <m.szyprowski@samsung.com> 7 * Marek Szyprowski <m.szyprowski@samsung.com>
8 * 8 *
9 * The vb2_thread implementation was based on code from videobuf-dvb.c:
10 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
11 *
9 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation. 14 * the Free Software Foundation.
@@ -18,6 +21,8 @@
18#include <linux/poll.h> 21#include <linux/poll.h>
19#include <linux/slab.h> 22#include <linux/slab.h>
20#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/freezer.h>
25#include <linux/kthread.h>
21 26
22#include <media/v4l2-dev.h> 27#include <media/v4l2-dev.h>
23#include <media/v4l2-fh.h> 28#include <media/v4l2-fh.h>
@@ -3005,6 +3010,147 @@ size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
3005} 3010}
3006EXPORT_SYMBOL_GPL(vb2_write); 3011EXPORT_SYMBOL_GPL(vb2_write);
3007 3012
3013struct vb2_threadio_data {
3014 struct task_struct *thread;
3015 vb2_thread_fnc fnc;
3016 void *priv;
3017 bool stop;
3018};
3019
3020static int vb2_thread(void *data)
3021{
3022 struct vb2_queue *q = data;
3023 struct vb2_threadio_data *threadio = q->threadio;
3024 struct vb2_fileio_data *fileio = q->fileio;
3025 bool set_timestamp = false;
3026 int prequeue = 0;
3027 int index = 0;
3028 int ret = 0;
3029
3030 if (V4L2_TYPE_IS_OUTPUT(q->type)) {
3031 prequeue = q->num_buffers;
3032 set_timestamp =
3033 (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
3034 V4L2_BUF_FLAG_TIMESTAMP_COPY;
3035 }
3036
3037 set_freezable();
3038
3039 for (;;) {
3040 struct vb2_buffer *vb;
3041
3042 /*
3043 * Call vb2_dqbuf to get buffer back.
3044 */
3045 memset(&fileio->b, 0, sizeof(fileio->b));
3046 fileio->b.type = q->type;
3047 fileio->b.memory = q->memory;
3048 if (prequeue) {
3049 fileio->b.index = index++;
3050 prequeue--;
3051 } else {
3052 call_void_qop(q, wait_finish, q);
3053 ret = vb2_internal_dqbuf(q, &fileio->b, 0);
3054 call_void_qop(q, wait_prepare, q);
3055 dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
3056 }
3057 if (threadio->stop)
3058 break;
3059 if (ret)
3060 break;
3061 try_to_freeze();
3062
3063 vb = q->bufs[fileio->b.index];
3064 if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
3065 ret = threadio->fnc(vb, threadio->priv);
3066 if (ret)
3067 break;
3068 call_void_qop(q, wait_finish, q);
3069 if (set_timestamp)
3070 v4l2_get_timestamp(&fileio->b.timestamp);
3071 ret = vb2_internal_qbuf(q, &fileio->b);
3072 call_void_qop(q, wait_prepare, q);
3073 if (ret)
3074 break;
3075 }
3076
3077 /* Hmm, linux becomes *very* unhappy without this ... */
3078 while (!kthread_should_stop()) {
3079 set_current_state(TASK_INTERRUPTIBLE);
3080 schedule();
3081 }
3082 return 0;
3083}
3084
3085/*
3086 * This function should not be used for anything else but the videobuf2-dvb
3087 * support. If you think you have another good use-case for this, then please
3088 * contact the linux-media mailinglist first.
3089 */
3090int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
3091 const char *thread_name)
3092{
3093 struct vb2_threadio_data *threadio;
3094 int ret = 0;
3095
3096 if (q->threadio)
3097 return -EBUSY;
3098 if (vb2_is_busy(q))
3099 return -EBUSY;
3100 if (WARN_ON(q->fileio))
3101 return -EBUSY;
3102
3103 threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
3104 if (threadio == NULL)
3105 return -ENOMEM;
3106 threadio->fnc = fnc;
3107 threadio->priv = priv;
3108
3109 ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
3110 dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
3111 if (ret)
3112 goto nomem;
3113 q->threadio = threadio;
3114 threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
3115 if (IS_ERR(threadio->thread)) {
3116 ret = PTR_ERR(threadio->thread);
3117 threadio->thread = NULL;
3118 goto nothread;
3119 }
3120 return 0;
3121
3122nothread:
3123 __vb2_cleanup_fileio(q);
3124nomem:
3125 kfree(threadio);
3126 return ret;
3127}
3128EXPORT_SYMBOL_GPL(vb2_thread_start);
3129
3130int vb2_thread_stop(struct vb2_queue *q)
3131{
3132 struct vb2_threadio_data *threadio = q->threadio;
3133 struct vb2_fileio_data *fileio = q->fileio;
3134 int err;
3135
3136 if (threadio == NULL)
3137 return 0;
3138 call_void_qop(q, wait_finish, q);
3139 threadio->stop = true;
3140 vb2_internal_streamoff(q, q->type);
3141 call_void_qop(q, wait_prepare, q);
3142 q->fileio = NULL;
3143 fileio->req.count = 0;
3144 vb2_reqbufs(q, &fileio->req);
3145 kfree(fileio);
3146 err = kthread_stop(threadio->thread);
3147 threadio->thread = NULL;
3148 kfree(threadio);
3149 q->fileio = NULL;
3150 q->threadio = NULL;
3151 return err;
3152}
3153EXPORT_SYMBOL_GPL(vb2_thread_stop);
3008 3154
3009/* 3155/*
3010 * The following functions are not part of the vb2 core API, but are helper 3156 * The following functions are not part of the vb2 core API, but are helper