From: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
To: Alexey Klimov <klimov.linux@gmail.com>
Cc: linux-media@vger.kernel.org, dron0gus@gmail.com,
tomasz.figa@gmail.com, oselas@community.pengutronix.de
Subject: Re: [PATCH RFC v3 1/3] V4L: Add driver for S3C244X/S3C64XX SoC series camera interface
Date: Fri, 16 Nov 2012 23:39:02 +0100 [thread overview]
Message-ID: <50A6C086.50208@gmail.com> (raw)
In-Reply-To: <CALW4P+KBd8fxCX8qSuZGYPx8pYj6LhEZfCurzuKuZzApe7Z7Aw@mail.gmail.com>
Hi Alexey,
On 11/16/2012 03:10 PM, Alexey Klimov wrote:
>>> +static int s3c_camif_hw_init(struct camif_dev *camif, struct camif_vp
>>> *vp)
>>> +{
>>> + unsigned int ip_rev = camif->variant->ip_revision;
>>> + unsigned long flags;
>>> +
>>> + if (camif->sensor.sd == NULL || vp->out_fmt == NULL)
>>> + return -EINVAL;
>>> +
>>> + spin_lock_irqsave(&camif->slock, flags);
>>> +
>>> + if (ip_rev == S3C244X_CAMIF_IP_REV)
>>> + camif_hw_clear_fifo_overflow(vp);
>>> + camif_hw_set_camera_bus(camif);
>>> + camif_hw_set_source_format(camif);
>>> + camif_hw_set_camera_crop(camif);
>>> + camif_hw_set_test_pattern(camif, camif->test_pattern->val);
>>> + if (ip_rev == S3C6410_CAMIF_IP_REV)
>>> + camif_hw_set_input_path(vp);
>>> + camif_cfg_video_path(vp);
>>> + vp->state&= ~ST_VP_CONFIG;
>>> +
>>> + spin_unlock_irqrestore(&camif->slock, flags);
>>> + return 0;
>>> +}
>>> +
>>> +/*
>>> + * Initialize the video path, only up from the scaler stage. The camera
>>> + * input interface set up is skipped. This is useful to enable one of
>>> the
>>> + * video paths when the other is already running.
>>> + */
>>> +static int s3c_camif_hw_vp_init(struct camif_dev *camif, struct camif_vp
>>> *vp)
>>> +{
>>> + unsigned int ip_rev = camif->variant->ip_revision;
>>> + unsigned long flags;
>>> +
>>> + if (vp->out_fmt == NULL)
>>> + return -EINVAL;
>>> +
>>> + spin_lock_irqsave(&camif->slock, flags);
>>> + camif_prepare_dma_offset(vp);
>>> + if (ip_rev == S3C244X_CAMIF_IP_REV)
>>> + camif_hw_clear_fifo_overflow(vp);
>>> + camif_cfg_video_path(vp);
>>> + if (ip_rev == S3C6410_CAMIF_IP_REV)
>>> + camif_hw_set_effect(vp, false);
>>> + vp->state&= ~ST_VP_CONFIG;
>>> +
>>> + spin_unlock_irqrestore(&camif->slock, flags);
>>> + return 0;
>>> +}
...
>>> +/*
>>> + * Reinitialize the driver so it is ready to start streaming again.
>>> + * Return any buffers to vb2, perform CAMIF software reset and
>>> + * turn off streaming at the data pipeline (sensor) if required.
>>> + */
>>> +static int camif_reinitialize(struct camif_vp *vp)
>>> +{
>>> + struct camif_dev *camif = vp->camif;
>>> + struct camif_buffer *buf;
>>> + unsigned long flags;
>>> + bool streaming;
>>> +
>>> + spin_lock_irqsave(&camif->slock, flags);
>>> + streaming = vp->state& ST_VP_SENSOR_STREAMING;
>>> +
>>> + vp->state&= ~(ST_VP_PENDING | ST_VP_RUNNING | ST_VP_OFF |
>>> + ST_VP_ABORTING | ST_VP_STREAMING |
>>> + ST_VP_SENSOR_STREAMING | ST_VP_LASTIRQ);
>>> +
>>> + /* Release unused buffers */
>>> + while (!list_empty(&vp->pending_buf_q)) {
>>> + buf = camif_pending_queue_pop(vp);
>>> + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
>>> + }
>>> +
>>> + while (!list_empty(&vp->active_buf_q)) {
>>> + buf = camif_active_queue_pop(vp);
>>> + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
>>> + }
>>> +
>>> + spin_unlock_irqrestore(&camif->slock, flags);
>>> +
>>> + if (!streaming)
>>> + return 0;
>>> +
>>> + return sensor_set_streaming(camif, 0);
>>> +}
...
>>> +static int start_streaming(struct vb2_queue *vq, unsigned int count)
>>> +{
>>> + struct camif_vp *vp = vb2_get_drv_priv(vq);
>>> + struct camif_dev *camif = vp->camif;
>>> + unsigned long flags;
>>> + int ret;
>>> +
>>> + /*
>>> + * We assume the codec capture path is always activated
>>> + * first, before the preview path starts streaming.
>>> + * This is required to avoid internal FIFO overflow and
>>> + * a need for CAMIF software reset.
>>> + */
>>> + spin_lock_irqsave(&camif->slock, flags);
>
> Here.
>
>>>
>>> +
>>> + if (camif->stream_count == 0) {
>>> + camif_hw_reset(camif);
>>> + spin_unlock_irqrestore(&camif->slock, flags);
>>> + ret = s3c_camif_hw_init(camif, vp);
>>> + } else {
>>> + spin_unlock_irqrestore(&camif->slock, flags);
>>> + ret = s3c_camif_hw_vp_init(camif, vp);
>>> + }
>>> +
>>> + if (ret< 0) {
>>> + camif_reinitialize(vp);
>>> + return ret;
>>> + }
>>> +
>>> + spin_lock_irqsave(&camif->slock, flags);
>
> Could you please check this function? Is it ok that you have double
> spin_lock_irqsave()? I don't know may be it's okay. Also when you call
> camif_reinitialize() you didn't call spin_unlock_irqrestore() before and
> inside camif_reinitialize() you will also call spin_lock_irqsave()..
Certainly with nested spinlock locking this code would have been useless.
I suppose this is what you mean by "double spin_lock_irqsave()". Since
it is known to work there must be spin_unlock_irqrestore() somewhere,
before the second spin_lock_irqsave() above. Just look around with more
focus ;)
Nevertheless, it looks locking can be removed from functions
s3c_camif_hw_init() and s3c_camif_vp_init(), those are called only from
one place, where in addition the spinlock is already held. I'm going
to squash following patch into that one:
----8<------
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c
b/drivers/media/platform/s3c-camif/camif-capture.c
index c2ecdcc..6401fdb 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -43,7 +43,7 @@
static int debug;
module_param(debug, int, 0644);
-/* Locking: called with vp->camif->slock held */
+/* Locking: called with vp->camif->slock spinlock held */
static void camif_cfg_video_path(struct camif_vp *vp)
{
WARN_ON(s3c_camif_get_scaler_config(vp, &vp->scaler));
@@ -64,16 +64,14 @@ static void camif_prepare_dma_offset(struct camif_vp
*vp)
f->dma_offset.initial, f->dma_offset.line);
}
+/* Locking: called with camif->slock spinlock held */
static int s3c_camif_hw_init(struct camif_dev *camif, struct camif_vp *vp)
{
const struct s3c_camif_variant *variant = camif->variant;
- unsigned long flags;
if (camif->sensor.sd == NULL || vp->out_fmt == NULL)
return -EINVAL;
- spin_lock_irqsave(&camif->slock, flags);
-
if (variant->ip_revision == S3C244X_CAMIF_IP_REV)
camif_hw_clear_fifo_overflow(vp);
camif_hw_set_camera_bus(camif);
@@ -88,7 +86,6 @@ static int s3c_camif_hw_init(struct camif_dev *camif,
struct camif_vp *vp)
camif_cfg_video_path(vp);
vp->state &= ~ST_VP_CONFIG;
- spin_unlock_irqrestore(&camif->slock, flags);
return 0;
}
@@ -96,23 +93,20 @@ static int s3c_camif_hw_init(struct camif_dev
*camif, struct camif_vp *vp)
* Initialize the video path, only up from the scaler stage. The camera
* input interface set up is skipped. This is useful to enable one of the
* video paths when the other is already running.
+ * Locking: called with camif->slock spinlock held.
*/
static int s3c_camif_hw_vp_init(struct camif_dev *camif, struct
camif_vp *vp)
{
unsigned int ip_rev = camif->variant->ip_revision;
- unsigned long flags;
if (vp->out_fmt == NULL)
return -EINVAL;
- spin_lock_irqsave(&camif->slock, flags);
camif_prepare_dma_offset(vp);
if (ip_rev == S3C244X_CAMIF_IP_REV)
camif_hw_clear_fifo_overflow(vp);
camif_cfg_video_path(vp);
vp->state &= ~ST_VP_CONFIG;
-
- spin_unlock_irqrestore(&camif->slock, flags);
return 0;
}
@@ -401,12 +395,11 @@ static int start_streaming(struct vb2_queue *vq,
unsigned int count)
if (camif->stream_count == 0) {
camif_hw_reset(camif);
- spin_unlock_irqrestore(&camif->slock, flags);
ret = s3c_camif_hw_init(camif, vp);
} else {
- spin_unlock_irqrestore(&camif->slock, flags);
ret = s3c_camif_hw_vp_init(camif, vp);
}
+ spin_unlock_irqrestore(&camif->slock, flags);
if (ret < 0) {
camif_reinitialize(vp);
@@ -437,8 +430,8 @@ static int start_streaming(struct vb2_queue *vq,
unsigned int count)
return ret;
}
}
- spin_unlock_irqrestore(&camif->slock, flags);
+ spin_unlock_irqrestore(&camif->slock, flags);
return 0;
}
---->8------
Thank you.
--
Regards,
Sylwester
next prev parent reply other threads:[~2012-11-16 22:39 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-15 22:05 [PATCH RFC v3 0/3] S3C244X/S3C64XX SoC series camera interface driver Sylwester Nawrocki
2012-11-15 22:05 ` [PATCH RFC v3 1/3] V4L: Add driver for S3C244X/S3C64XX SoC series camera interface Sylwester Nawrocki
2012-11-16 13:45 ` Hans Verkuil
2012-11-17 18:24 ` Sylwester Nawrocki
[not found] ` <CALW4P+JQUcywagZAe5qHRifsSwAnKoDccmhpQ=TSWvxcS-6CqA@mail.gmail.com>
2012-11-16 14:10 ` Alexey Klimov
2012-11-16 22:39 ` Sylwester Nawrocki [this message]
2012-11-25 23:21 ` Alexey Klimov
2012-11-15 22:05 ` [PATCH RFC v3 2/3] s3c-camif: Add image effect controls Sylwester Nawrocki
2012-11-15 22:05 ` [PATCH RFC v3 3/3] MAINTAINERS: Add entry for S3C24XX/S3C64XX SoC CAMIF driver Sylwester Nawrocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50A6C086.50208@gmail.com \
--to=sylvester.nawrocki@gmail.com \
--cc=dron0gus@gmail.com \
--cc=klimov.linux@gmail.com \
--cc=linux-media@vger.kernel.org \
--cc=oselas@community.pengutronix.de \
--cc=tomasz.figa@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.