public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
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,&reg, 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,&reg);
> -		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

  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