diff options
author | Bryan Wu <pengw@nvidia.com> | 2015-10-14 11:52:57 -0700 |
---|---|---|
committer | Matthew Pedro <mapedro@nvidia.com> | 2015-10-29 10:52:30 -0700 |
commit | b15d976c0a2e6a3c512001a3be3feaf057655b8b (patch) | |
tree | f1669c0ab6c34d4ebdb909e882d6a6c22c5c2b09 /drivers | |
parent | e46e60ceb990edf4e28db1685e28847e8dfca4b3 (diff) |
media: tegra_camera: replace workqueue with kthread
Use kthread instead of workqueue, which will create a dedicated kernel
thread for capture.
Remove useless mutex and convert spin_lock_irq() to normal spin_lock().
Bug 1686911
Change-Id: Ib236a7ebbdd0359f2705774a979825f1f9e9d82a
Signed-off-by: Bryan Wu <pengw@nvidia.com>
Reviewed-on: http://git-master/r/819176
GVS: Gerrit_Virtual_Submit
Reviewed-by: Matthew Pedro <mapedro@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/platform/soc_camera/tegra_camera/common.c | 69 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/tegra_camera/common.h | 4 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/tegra_camera/vi2.c | 2 |
3 files changed, 38 insertions, 37 deletions
diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.c b/drivers/media/platform/soc_camera/tegra_camera/common.c index 2fa4d78a7add..888d0aed96d3 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/common.c +++ b/drivers/media/platform/soc_camera/tegra_camera/common.c @@ -16,6 +16,8 @@ #include <linux/delay.h> #include <linux/kernel.h> +#include <linux/kthread.h> +#include <linux/freezer.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/nvhost.h> @@ -247,7 +249,7 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *cam) cam->ops->capture_setup(cam); } - spin_lock_irq(&cam->videobuf_queue_lock); + spin_lock(&cam->videobuf_queue_lock); vb = cam->active; do_gettimeofday(&vb->v4l2_buf.timestamp); @@ -262,37 +264,41 @@ static int tegra_camera_capture_frame(struct tegra_camera_dev *cam) cam->num_frames++; - spin_unlock_irq(&cam->videobuf_queue_lock); + spin_unlock(&cam->videobuf_queue_lock); return err; } -static void tegra_camera_work(struct work_struct *work) +static int tegra_camera_kthread_capture(void *data) { - struct tegra_camera_dev *cam = - container_of(work, struct tegra_camera_dev, work); + struct tegra_camera_dev *cam = data; struct tegra_camera_buffer *buf; while (1) { - mutex_lock(&cam->work_mutex); + try_to_freeze(); - spin_lock_irq(&cam->videobuf_queue_lock); + wait_event_interruptible(cam->wait, + !list_empty(&cam->capture) || + kthread_should_stop()); + if (kthread_should_stop()) + break; + + spin_lock(&cam->videobuf_queue_lock); if (list_empty(&cam->capture)) { cam->active = NULL; - spin_unlock_irq(&cam->videobuf_queue_lock); - mutex_unlock(&cam->work_mutex); - return; + spin_unlock(&cam->videobuf_queue_lock); + continue; } buf = list_entry(cam->capture.next, struct tegra_camera_buffer, - queue); + queue); cam->active = &buf->vb; - spin_unlock_irq(&cam->videobuf_queue_lock); + spin_unlock(&cam->videobuf_queue_lock); tegra_camera_capture_frame(cam); - - mutex_unlock(&cam->work_mutex); } + + return 0; } static int tegra_camera_init_buffer(struct tegra_camera_buffer *buf) @@ -481,12 +487,12 @@ static void tegra_camera_videobuf_queue(struct vb2_buffer *vb) struct tegra_camera_dev *cam = ici->priv; struct tegra_camera_buffer *buf = to_tegra_vb(vb); - spin_lock_irq(&cam->videobuf_queue_lock); + spin_lock(&cam->videobuf_queue_lock); list_add_tail(&buf->queue, &cam->capture); - spin_unlock_irq(&cam->videobuf_queue_lock); + spin_unlock(&cam->videobuf_queue_lock); - if (vb2_is_streaming(vb->vb2_queue)) - schedule_work(&cam->work); + /* Wait up kthread for capture */ + wake_up_interruptible(&cam->wait); } static void tegra_camera_videobuf_release(struct vb2_buffer *vb) @@ -498,9 +504,7 @@ static void tegra_camera_videobuf_release(struct vb2_buffer *vb) struct tegra_camera_buffer *buf = to_tegra_vb(vb); struct tegra_camera_dev *cam = ici->priv; - mutex_lock(&cam->work_mutex); - - spin_lock_irq(&cam->videobuf_queue_lock); + spin_lock(&cam->videobuf_queue_lock); if (cam->active == vb) cam->active = NULL; @@ -512,9 +516,7 @@ static void tegra_camera_videobuf_release(struct vb2_buffer *vb) if (buf->queue.next) list_del_init(&buf->queue); - spin_unlock_irq(&cam->videobuf_queue_lock); - - mutex_unlock(&cam->work_mutex); + spin_unlock(&cam->videobuf_queue_lock); } static int tegra_camera_videobuf_init(struct vb2_buffer *vb) @@ -533,8 +535,9 @@ static int tegra_camera_start_streaming(struct vb2_queue *q, unsigned int count) struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct tegra_camera_dev *cam = ici->priv; - schedule_work(&cam->work); - + /* Start kthread to capture data to buffer */ + cam->kthread_capture = kthread_run(tegra_camera_kthread_capture, cam, + dev_name(&cam->ndev->dev)); return 0; } @@ -547,11 +550,14 @@ static int tegra_camera_stop_streaming(struct vb2_queue *q) struct tegra_camera_dev *cam = ici->priv; struct soc_camera_subdev_desc *ssdesc = &icd->sdesc->subdev_desc; struct tegra_camera_platform_data *pdata = ssdesc->drv_priv; + struct tegra_camera_buffer *buf, *nbuf; int port = pdata->port; - mutex_lock(&cam->work_mutex); + /* Stop the kthread for capture */ + kthread_stop(cam->kthread_capture); + cam->kthread_capture = NULL; + cam->ops->capture_stop(cam, port); - mutex_unlock(&cam->work_mutex); return 0; } @@ -612,10 +618,8 @@ static void tegra_camera_remove_device(struct soc_camera_device *icd) struct tegra_camera_dev *cam = ici->priv; cam->enable_refcnt--; - if (!cam->enable_refcnt) { - cancel_work_sync(&cam->work); + if (!cam->enable_refcnt) tegra_camera_deactivate(cam); - } } static int tegra_camera_set_bus_param(struct soc_camera_device *icd) @@ -909,9 +913,8 @@ static int tegra_camera_probe(struct platform_device *pdev) cam->tpg_mode = tpg_mode; INIT_LIST_HEAD(&cam->capture); - INIT_WORK(&cam->work, tegra_camera_work); spin_lock_init(&cam->videobuf_queue_lock); - mutex_init(&cam->work_mutex); + init_waitqueue_head(&cam->wait); if (pdev->dev.of_node) { int cplen; diff --git a/drivers/media/platform/soc_camera/tegra_camera/common.h b/drivers/media/platform/soc_camera/tegra_camera/common.h index 18da08cb6a86..c27c83cd4558 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/common.h +++ b/drivers/media/platform/soc_camera/tegra_camera/common.h @@ -101,8 +101,8 @@ struct tegra_camera_dev { int sequence_a; int sequence_b; - struct work_struct work; - struct mutex work_mutex; + struct task_struct *kthread_capture; + wait_queue_head_t wait; /* syncpt ids */ u32 syncpt_id_csi_a; diff --git a/drivers/media/platform/soc_camera/tegra_camera/vi2.c b/drivers/media/platform/soc_camera/tegra_camera/vi2.c index 4d17cda6046e..aaf6d2734ce3 100644 --- a/drivers/media/platform/soc_camera/tegra_camera/vi2.c +++ b/drivers/media/platform/soc_camera/tegra_camera/vi2.c @@ -1104,8 +1104,6 @@ static void vi2_sw_reset(struct tegra_camera_dev *cam) udelay(10); } - - static int vi2_mipi_calibration(struct tegra_camera_dev *cam) { void __iomem *mipi_cal; |