From: Sylwester Nawrocki <snjw23@gmail.com>
To: "HeungJun, Kim" <riverful.kim@samsung.com>
Cc: linux-media@vger.kernel.org, Kyungmin Park <kyungmin.park@samsung.com>
Subject: Re: [PATCH 2/5] m5mols: Replace IRQ workqueue to waitqueue only
Date: Tue, 15 Nov 2011 00:04:20 +0100 [thread overview]
Message-ID: <4EC19E74.2070205@gmail.com> (raw)
In-Reply-To: <1319182554-10645-2-git-send-email-riverful.kim@samsung.com>
On 10/21/2011 09:35 AM, HeungJun, Kim wrote:
> In M-5MOLS driver, the workqueue code for IRQ is hard to re-use. So, remove
> the IRQ workqueue, and use only waitqueue for waiting IRQ with timeout.
> The info->issue has the status that interrupt is issued or not, then
> the info->interrupt has the IRQ status register at that time.
>
> Signed-off-by: HeungJun, Kim<riverful.kim@samsung.com>
> Signed-off-by: Kyungmin Park<kyungmin.park@samsung.com>
> ---
> drivers/media/video/m5mols/m5mols.h | 7 +--
> drivers/media/video/m5mols/m5mols_capture.c | 34 ++-------------
> drivers/media/video/m5mols/m5mols_core.c | 60 +++++++++++----------------
> 3 files changed, 32 insertions(+), 69 deletions(-)
>
> diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h
> index c8e1572..75f7984 100644
> --- a/drivers/media/video/m5mols/m5mols.h
> +++ b/drivers/media/video/m5mols/m5mols.h
> @@ -164,7 +164,6 @@ struct m5mols_version {
> * @res_type: current resolution type
> * @code: current code
> * @irq_waitq: waitqueue for the capture
> - * @work_irq: workqueue for the IRQ
> * @flags: state variable for the interrupt handler
> * @handle: control handler
> * @autoexposure: Auto Exposure control
> @@ -181,6 +180,7 @@ struct m5mols_version {
> * @lock_ae: true means the Auto Exposure is locked
> * @lock_awb: true means the Aut WhiteBalance is locked
> * @resolution: register value for current resolution
> + * @issue: "true" means the M-5MOLS sensor's interrupt issued
> * @interrupt: register value for current interrupt status
> * @mode: register value for current operation mode
> * @mode_save: register value for current operation mode for saving
> @@ -194,7 +194,6 @@ struct m5mols_info {
> int res_type;
> enum v4l2_mbus_pixelcode code;
> wait_queue_head_t irq_waitq;
> - struct work_struct work_irq;
> unsigned long flags;
>
> struct v4l2_ctrl_handler handle;
> @@ -211,6 +210,7 @@ struct m5mols_info {
> struct m5mols_version ver;
> struct m5mols_capture cap;
> bool power;
> + bool issue;
> bool ctrl_sync;
> bool lock_ae;
> bool lock_awb;
> @@ -221,8 +221,6 @@ struct m5mols_info {
> int (*set_power)(struct device *dev, int on);
> };
>
> -#define ST_CAPT_IRQ 0
> -
> #define is_powered(__info) (__info->power)
> #define is_ctrl_synced(__info) (__info->ctrl_sync)
> #define is_available_af(__info) (__info->ver.af)
> @@ -283,6 +281,7 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
> int m5mols_mode(struct m5mols_info *info, u8 mode);
>
> int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
> +int m5mols_timeout_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout);
> int m5mols_sync_controls(struct m5mols_info *info);
> int m5mols_start_capture(struct m5mols_info *info);
> int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
> diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c
> index 3248ac8..18a56bf 100644
> --- a/drivers/media/video/m5mols/m5mols_capture.c
> +++ b/drivers/media/video/m5mols/m5mols_capture.c
> @@ -29,22 +29,6 @@
> #include "m5mols.h"
> #include "m5mols_reg.h"
>
> -static int m5mols_capture_error_handler(struct m5mols_info *info,
> - int timeout)
> -{
> - int ret;
> -
> - /* Disable all interrupts and clear relevant interrupt staus bits */
> - ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE,
> - info->interrupt& ~(REG_INT_CAPTURE));
> - if (ret)
> - return ret;
> -
> - if (timeout == 0)
> - return -ETIMEDOUT;
> -
> - return 0;
> -}
> /**
> * m5mols_read_rational - I2C read of a rational number
> *
> @@ -121,7 +105,6 @@ int m5mols_start_capture(struct m5mols_info *info)
> {
> struct v4l2_subdev *sd =&info->sd;
> u8 resolution = info->resolution;
> - int timeout;
> int ret;
>
> /*
> @@ -142,14 +125,9 @@ int m5mols_start_capture(struct m5mols_info *info)
> ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
> if (!ret)
> ret = m5mols_mode(info, REG_CAPTURE);
> - if (!ret) {
> + if (!ret)
> /* Wait for capture interrupt, after changing capture mode */
> - timeout = wait_event_interruptible_timeout(info->irq_waitq,
> - test_bit(ST_CAPT_IRQ,&info->flags),
> - msecs_to_jiffies(2000));
> - if (test_and_clear_bit(ST_CAPT_IRQ,&info->flags))
> - ret = m5mols_capture_error_handler(info, timeout);
> - }
> + ret = m5mols_timeout_interrupt(sd, REG_INT_CAPTURE, 2000);
> if (!ret)
> ret = m5mols_lock_3a(info, false);
> if (ret)
> @@ -175,15 +153,13 @@ int m5mols_start_capture(struct m5mols_info *info)
> ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
> if (!ret) {
> /* Wait for the capture completion interrupt */
> - timeout = wait_event_interruptible_timeout(info->irq_waitq,
> - test_bit(ST_CAPT_IRQ,&info->flags),
> - msecs_to_jiffies(2000));
> - if (test_and_clear_bit(ST_CAPT_IRQ,&info->flags)) {
> + ret = m5mols_timeout_interrupt(sd, REG_INT_CAPTURE, 2000);
> + if (!ret) {
> ret = m5mols_capture_info(info);
> if (!ret)
> v4l2_subdev_notify(sd, 0,&info->cap.total);
> }
> }
>
> - return m5mols_capture_error_handler(info, timeout);
> + return ret;
> }
> diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c
> index 73db96e..f3b9415 100644
> --- a/drivers/media/video/m5mols/m5mols_core.c
> +++ b/drivers/media/video/m5mols/m5mols_core.c
> @@ -333,6 +333,28 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
> return ret;
> }
>
> +/* m5mols_timeout_interrupt - Wait interrupt and figure out which interrupt. */
> +int m5mols_timeout_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout)
Could this be m5mols_wait_interrupt() instead ?
> +{
> + struct m5mols_info *info = to_m5mols(sd);
> + u8 reg;
> + int timed;
> + int ret;
> +
> + timed = wait_event_interruptible_timeout(info->irq_waitq,
> + info->issue, msecs_to_jiffies(timeout));
I'm a bit sceptic about replacing current atomic test with a non atomic one.
Using bit operations (test_and_clear_bit() ?) could probably save us from loosing
any interrupt. Still, there might be no problem if you're careful enough.
> + if (!timed)
> + return -ETIMEDOUT;
> +
> + ret = m5mols_busy_val(sd, condition,®, CAT_SYSTEM, CAT0_INT_FACTOR);
> + if (ret || (!ret&& reg != condition))
It could be simplified to:
if (ret || reg != condition)
> + return -EINVAL;
> +
> + info->interrupt = reg;
> + info->issue = false;
I think this might be racy, as this variable is also being changed in the interrupt
handler.
> + return 0;
> +}
> +
> /**
> * m5mols_reg_mode - Write the mode and check busy status
> *
> @@ -901,46 +923,13 @@ static const struct v4l2_subdev_ops m5mols_ops = {
> .video =&m5mols_video_ops,
> };
>
> -static void m5mols_irq_work(struct work_struct *work)
> -{
> - struct m5mols_info *info =
> - container_of(work, struct m5mols_info, work_irq);
> - struct v4l2_subdev *sd =&info->sd;
> - u8 reg;
> - int ret;
> -
> - if (!is_powered(info) ||
> - m5mols_read_u8(sd, SYSTEM_INT_FACTOR,&info->interrupt))
> - return;
> -
> - switch (info->interrupt& REG_INT_MASK) {
> - case REG_INT_AF:
> - if (!is_available_af(info))
> - break;
> - ret = m5mols_read_u8(sd, AF_STATUS,®);
> - v4l2_dbg(2, m5mols_debug, sd, "AF %s\n",
> - reg == REG_AF_FAIL ? "Failed" :
> - reg == REG_AF_SUCCESS ? "Success" :
> - reg == REG_AF_IDLE ? "Idle" : "Busy");
> - break;
> - case REG_INT_CAPTURE:
> - if (!test_and_set_bit(ST_CAPT_IRQ,&info->flags))
> - wake_up_interruptible(&info->irq_waitq);
> -
> - v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n");
> - break;
> - default:
> - v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg);
> - break;
> - };
> -}
> -
> static irqreturn_t m5mols_irq_handler(int irq, void *data)
> {
> struct v4l2_subdev *sd = data;
> struct m5mols_info *info = to_m5mols(sd);
>
> - schedule_work(&info->work_irq);
> + info->issue = true;
> + wake_up_interruptible(&info->irq_waitq);
>
> return IRQ_HANDLED;
> }
> @@ -999,7 +988,6 @@ static int __devinit m5mols_probe(struct i2c_client *client,
> sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
>
> init_waitqueue_head(&info->irq_waitq);
> - INIT_WORK(&info->work_irq, m5mols_irq_work);
> ret = request_irq(client->irq, m5mols_irq_handler,
> IRQF_TRIGGER_RISING, MODULE_NAME, sd);
> if (ret) {
--
Regards,
Sylwester
next prev parent reply other threads:[~2011-11-14 23:04 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-21 7:35 [PATCH 1/5] m5mols: Add more functions to check busy status HeungJun, Kim
2011-10-21 7:35 ` [PATCH 2/5] m5mols: Replace IRQ workqueue to waitqueue only HeungJun, Kim
2011-11-14 23:04 ` Sylwester Nawrocki [this message]
2011-11-15 7:31 ` HeungJun, Kim
2011-10-21 7:35 ` [PATCH 3/5] m5mols: Support for interrupt in the sensor's booting time HeungJun, Kim
2011-10-21 7:35 ` [PATCH 4/5] m5mols: Add boot flag for not showing the msg of I2C error HeungJun, Kim
2011-11-14 22:35 ` Sylwester Nawrocki
2011-11-15 7:05 ` HeungJun, Kim
2011-10-21 7:35 ` [PATCH 5/5] m5mols: Relocation the order and count for CAPTURE interrupt HeungJun, Kim
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=4EC19E74.2070205@gmail.com \
--to=snjw23@gmail.com \
--cc=kyungmin.park@samsung.com \
--cc=linux-media@vger.kernel.org \
--cc=riverful.kim@samsung.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox