linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
       [not found] <1365048389-6364-1-git-send-email-naveenkrishna.ch@gmail.com>
@ 2013-10-11  8:23 ` Naveen Krishna Chatradhi
  2013-10-11 14:30   ` Lars-Peter Clausen
                     ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Naveen Krishna Chatradhi @ 2013-10-11  8:23 UTC (permalink / raw)
  To: linux-iio
  Cc: linux-kernel, linux-samsung-soc, dianders, gregkh,
	naveenkrishna.ch, lars, tomasz.figa

This patch does the following
1. use wait_for_completion_timeout instead of
   wait_for_completion_interruptible_timeout
2. Reset software if a timeout happens.
3. Also reduce the timeout to 100milli secs

Note: submitted for review at https://patchwork.kernel.org/patch/2279591/

Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Cc: Doug Anderson <dianders@chromium.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes since v1:
As per discussion at
http://marc.info/?l=linux-kernel&m=136517637228869&w=3

This patch does the following
1. use wait_for_completion_timeout instead of
   wait_for_completion_interruptible_timeout
2. Reset software if a timeout happens.
3. Also reduce the timeout to 100milli secs

Changes since v2:
None.
Rebased and reposting.

---
 drivers/iio/adc/exynos_adc.c |   66 +++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 30 deletions(-)

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index d25b262..f18ed7e 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -82,7 +82,7 @@ enum adc_version {
 #define ADC_CON_EN_START	(1u << 0)
 #define ADC_DATX_MASK		0xFFF
 
-#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(1000))
+#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(100))
 
 struct exynos_adc {
 	void __iomem		*regs;
@@ -112,6 +112,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
 	return (unsigned int)match->data;
 }
 
+static void exynos_adc_hw_init(struct exynos_adc *info)
+{
+	u32 con1, con2;
+
+	if (info->version == ADC_V2) {
+		con1 = ADC_V2_CON1_SOFT_RESET;
+		writel(con1, ADC_V2_CON1(info->regs));
+
+		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+		writel(con2, ADC_V2_CON2(info->regs));
+
+		/* Enable interrupts */
+		writel(1, ADC_V2_INT_EN(info->regs));
+	} else {
+		/* set default prescaler values and Enable prescaler */
+		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+		/* Enable 12-bit ADC resolution */
+		con1 |= ADC_V1_CON_RES;
+		writel(con1, ADC_V1_CON(info->regs));
+	}
+}
+
 static int exynos_read_raw(struct iio_dev *indio_dev,
 				struct iio_chan_spec const *chan,
 				int *val,
@@ -121,6 +145,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 	struct exynos_adc *info = iio_priv(indio_dev);
 	unsigned long timeout;
 	u32 con1, con2;
+	int ret;
 
 	if (mask != IIO_CHAN_INFO_RAW)
 		return -EINVAL;
@@ -145,16 +170,21 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 				ADC_V1_CON(info->regs));
 	}
 
-	timeout = wait_for_completion_interruptible_timeout
+	timeout = wait_for_completion_timeout
 			(&info->completion, EXYNOS_ADC_TIMEOUT);
+	if (timeout == 0) {
+		dev_warn(&indio_dev->dev, "Conversion timed out reseting\n");
+		exynos_adc_hw_init(info);
+		ret = -ETIMEDOUT;
+	} else {
+		*val = info->value;
+		ret = IIO_VAL_INT;
+	}
 	*val = info->value;
 
 	mutex_unlock(&indio_dev->mlock);
 
-	if (timeout == 0)
-		return -ETIMEDOUT;
-
-	return IIO_VAL_INT;
+	return ret;
 }
 
 static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
@@ -226,30 +256,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
 	return 0;
 }
 
-static void exynos_adc_hw_init(struct exynos_adc *info)
-{
-	u32 con1, con2;
-
-	if (info->version == ADC_V2) {
-		con1 = ADC_V2_CON1_SOFT_RESET;
-		writel(con1, ADC_V2_CON1(info->regs));
-
-		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
-			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
-		writel(con2, ADC_V2_CON2(info->regs));
-
-		/* Enable interrupts */
-		writel(1, ADC_V2_INT_EN(info->regs));
-	} else {
-		/* set default prescaler values and Enable prescaler */
-		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
-
-		/* Enable 12-bit ADC resolution */
-		con1 |= ADC_V1_CON_RES;
-		writel(con1, ADC_V1_CON(info->regs));
-	}
-}
-
 static int exynos_adc_probe(struct platform_device *pdev)
 {
 	struct exynos_adc *info = NULL;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
  2013-10-11  8:23 ` [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible Naveen Krishna Chatradhi
@ 2013-10-11 14:30   ` Lars-Peter Clausen
  2013-10-12  6:40     ` Naveen Krishna Ch
  2013-10-15  5:15   ` [PATCH v4] " Naveen Krishna Chatradhi
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Lars-Peter Clausen @ 2013-10-11 14:30 UTC (permalink / raw)
  To: Naveen Krishna Chatradhi
  Cc: linux-iio, linux-kernel, linux-samsung-soc, dianders, gregkh,
	naveenkrishna.ch, tomasz.figa

On 10/11/2013 10:23 AM, Naveen Krishna Chatradhi wrote:
> This patch does the following
> 1. use wait_for_completion_timeout instead of
>    wait_for_completion_interruptible_timeout
> 2. Reset software if a timeout happens.
> 3. Also reduce the timeout to 100milli secs

It is always good to have a description of why a chance should be done in
the commit message. It is obvious what the patch does by just looking at the
changed lines, it is not that obvious though why those lines had to be changed.

> 
> Note: submitted for review at https://patchwork.kernel.org/patch/2279591/
> 
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Cc: Doug Anderson <dianders@chromium.org>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> ---
> Changes since v1:
> As per discussion at
> http://marc.info/?l=linux-kernel&m=136517637228869&w=3
> 
> This patch does the following
> 1. use wait_for_completion_timeout instead of
>    wait_for_completion_interruptible_timeout
> 2. Reset software if a timeout happens.
> 3. Also reduce the timeout to 100milli secs
> 
> Changes since v2:
> None.
> Rebased and reposting.
> 
> ---
>  drivers/iio/adc/exynos_adc.c |   66 +++++++++++++++++++++++-------------------
>  1 file changed, 36 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
> index d25b262..f18ed7e 100644
> --- a/drivers/iio/adc/exynos_adc.c
> +++ b/drivers/iio/adc/exynos_adc.c
> @@ -82,7 +82,7 @@ enum adc_version {
>  #define ADC_CON_EN_START	(1u << 0)
>  #define ADC_DATX_MASK		0xFFF
>  
> -#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(1000))
> +#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(100))
>  
>  struct exynos_adc {
>  	void __iomem		*regs;
> @@ -112,6 +112,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
>  	return (unsigned int)match->data;
>  }
>  
> +static void exynos_adc_hw_init(struct exynos_adc *info)
> +{
> +	u32 con1, con2;
> +
> +	if (info->version == ADC_V2) {
> +		con1 = ADC_V2_CON1_SOFT_RESET;
> +		writel(con1, ADC_V2_CON1(info->regs));
> +
> +		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
> +			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
> +		writel(con2, ADC_V2_CON2(info->regs));
> +
> +		/* Enable interrupts */
> +		writel(1, ADC_V2_INT_EN(info->regs));
> +	} else {
> +		/* set default prescaler values and Enable prescaler */
> +		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
> +
> +		/* Enable 12-bit ADC resolution */
> +		con1 |= ADC_V1_CON_RES;
> +		writel(con1, ADC_V1_CON(info->regs));
> +	}
> +}
> +
>  static int exynos_read_raw(struct iio_dev *indio_dev,
>  				struct iio_chan_spec const *chan,
>  				int *val,
> @@ -121,6 +145,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
>  	struct exynos_adc *info = iio_priv(indio_dev);
>  	unsigned long timeout;
>  	u32 con1, con2;
> +	int ret;
>  
>  	if (mask != IIO_CHAN_INFO_RAW)
>  		return -EINVAL;
> @@ -145,16 +170,21 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
>  				ADC_V1_CON(info->regs));
>  	}
>  
> -	timeout = wait_for_completion_interruptible_timeout
> +	timeout = wait_for_completion_timeout
>  			(&info->completion, EXYNOS_ADC_TIMEOUT);

Nitpick: It would be nice to put the &info->completion on the same line as
the wait_for_completion...

> +	if (timeout == 0) {
> +		dev_warn(&indio_dev->dev, "Conversion timed out reseting\n");
> +		exynos_adc_hw_init(info);
> +		ret = -ETIMEDOUT;
> +	} else {
> +		*val = info->value;
> +		ret = IIO_VAL_INT;
> +	}
>  	*val = info->value;

This line above should probably be removed.

>  
>  	mutex_unlock(&indio_dev->mlock);
>  
> -	if (timeout == 0)
> -		return -ETIMEDOUT;
> -
> -	return IIO_VAL_INT;
> +	return ret;
>  }
>  
>  static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
> @@ -226,30 +256,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
>  	return 0;
>  }
>  
> -static void exynos_adc_hw_init(struct exynos_adc *info)
> -{
> -	u32 con1, con2;
> -
> -	if (info->version == ADC_V2) {
> -		con1 = ADC_V2_CON1_SOFT_RESET;
> -		writel(con1, ADC_V2_CON1(info->regs));
> -
> -		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
> -			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
> -		writel(con2, ADC_V2_CON2(info->regs));
> -
> -		/* Enable interrupts */
> -		writel(1, ADC_V2_INT_EN(info->regs));
> -	} else {
> -		/* set default prescaler values and Enable prescaler */
> -		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
> -
> -		/* Enable 12-bit ADC resolution */
> -		con1 |= ADC_V1_CON_RES;
> -		writel(con1, ADC_V1_CON(info->regs));
> -	}
> -}
> -
>  static int exynos_adc_probe(struct platform_device *pdev)
>  {
>  	struct exynos_adc *info = NULL;
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
  2013-10-11 14:30   ` Lars-Peter Clausen
@ 2013-10-12  6:40     ` Naveen Krishna Ch
  0 siblings, 0 replies; 8+ messages in thread
From: Naveen Krishna Ch @ 2013-10-12  6:40 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Naveen Krishna Chatradhi, linux-iio, linux-kernel,
	linux-samsung-soc, dianders, gregkh, tomasz.figa

On 11 October 2013 20:00, Lars-Peter Clausen <lars@metafoo.de> wrote:
> On 10/11/2013 10:23 AM, Naveen Krishna Chatradhi wrote:
>> This patch does the following
>> 1. use wait_for_completion_timeout instead of
>>    wait_for_completion_interruptible_timeout
>> 2. Reset software if a timeout happens.
>> 3. Also reduce the timeout to 100milli secs
>
> It is always good to have a description of why a chance should be done in
> the commit message. It is obvious what the patch does by just looking at the
> changed lines, it is not that obvious though why those lines had to be changed.
>
>>
>> Note: submitted for review at https://patchwork.kernel.org/patch/2279591/
>>
>> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
>> Cc: Doug Anderson <dianders@chromium.org>
>> Cc: Lars-Peter Clausen <lars@metafoo.de>
>> ---
>> Changes since v1:
>> As per discussion at
>> http://marc.info/?l=linux-kernel&m=136517637228869&w=3
>>
>> This patch does the following
>> 1. use wait_for_completion_timeout instead of
>>    wait_for_completion_interruptible_timeout
>> 2. Reset software if a timeout happens.
>> 3. Also reduce the timeout to 100milli secs
>>
>> Changes since v2:
>> None.
>> Rebased and reposting.
>>
>> ---
>>  drivers/iio/adc/exynos_adc.c |   66 +++++++++++++++++++++++-------------------
>>  1 file changed, 36 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
>> index d25b262..f18ed7e 100644
>> --- a/drivers/iio/adc/exynos_adc.c
>> +++ b/drivers/iio/adc/exynos_adc.c
>> @@ -82,7 +82,7 @@ enum adc_version {
>>  #define ADC_CON_EN_START     (1u << 0)
>>  #define ADC_DATX_MASK                0xFFF
>>
>> -#define EXYNOS_ADC_TIMEOUT   (msecs_to_jiffies(1000))
>> +#define EXYNOS_ADC_TIMEOUT   (msecs_to_jiffies(100))
>>
>>  struct exynos_adc {
>>       void __iomem            *regs;
>> @@ -112,6 +112,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
>>       return (unsigned int)match->data;
>>  }
>>
>> +static void exynos_adc_hw_init(struct exynos_adc *info)
>> +{
>> +     u32 con1, con2;
>> +
>> +     if (info->version == ADC_V2) {
>> +             con1 = ADC_V2_CON1_SOFT_RESET;
>> +             writel(con1, ADC_V2_CON1(info->regs));
>> +
>> +             con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
>> +                     ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
>> +             writel(con2, ADC_V2_CON2(info->regs));
>> +
>> +             /* Enable interrupts */
>> +             writel(1, ADC_V2_INT_EN(info->regs));
>> +     } else {
>> +             /* set default prescaler values and Enable prescaler */
>> +             con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
>> +
>> +             /* Enable 12-bit ADC resolution */
>> +             con1 |= ADC_V1_CON_RES;
>> +             writel(con1, ADC_V1_CON(info->regs));
>> +     }
>> +}
>> +
>>  static int exynos_read_raw(struct iio_dev *indio_dev,
>>                               struct iio_chan_spec const *chan,
>>                               int *val,
>> @@ -121,6 +145,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
>>       struct exynos_adc *info = iio_priv(indio_dev);
>>       unsigned long timeout;
>>       u32 con1, con2;
>> +     int ret;
>>
>>       if (mask != IIO_CHAN_INFO_RAW)
>>               return -EINVAL;
>> @@ -145,16 +170,21 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
>>                               ADC_V1_CON(info->regs));
>>       }
>>
>> -     timeout = wait_for_completion_interruptible_timeout
>> +     timeout = wait_for_completion_timeout
>>                       (&info->completion, EXYNOS_ADC_TIMEOUT);
>
> Nitpick: It would be nice to put the &info->completion on the same line as
> the wait_for_completion...
I received a comment from Grant regarding the same.
I'm away from work this weekend. Will submit the code once i get back,
>
>> +     if (timeout == 0) {
>> +             dev_warn(&indio_dev->dev, "Conversion timed out reseting\n");
>> +             exynos_adc_hw_init(info);
>> +             ret = -ETIMEDOUT;
>> +     } else {
>> +             *val = info->value;
>> +             ret = IIO_VAL_INT;
>> +     }
>>       *val = info->value;
>
> This line above should probably be removed.
Yes this is unnecessary. Will remove this.
>
>>
>>       mutex_unlock(&indio_dev->mlock);
>>
>> -     if (timeout == 0)
>> -             return -ETIMEDOUT;
>> -
>> -     return IIO_VAL_INT;
>> +     return ret;
>>  }
>>
>>  static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
>> @@ -226,30 +256,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
>>       return 0;
>>  }
>>
>> -static void exynos_adc_hw_init(struct exynos_adc *info)
>> -{
>> -     u32 con1, con2;
>> -
>> -     if (info->version == ADC_V2) {
>> -             con1 = ADC_V2_CON1_SOFT_RESET;
>> -             writel(con1, ADC_V2_CON1(info->regs));
>> -
>> -             con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
>> -                     ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
>> -             writel(con2, ADC_V2_CON2(info->regs));
>> -
>> -             /* Enable interrupts */
>> -             writel(1, ADC_V2_INT_EN(info->regs));
>> -     } else {
>> -             /* set default prescaler values and Enable prescaler */
>> -             con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
>> -
>> -             /* Enable 12-bit ADC resolution */
>> -             con1 |= ADC_V1_CON_RES;
>> -             writel(con1, ADC_V1_CON(info->regs));
>> -     }
>> -}
>> -
>>  static int exynos_adc_probe(struct platform_device *pdev)
>>  {
>>       struct exynos_adc *info = NULL;
>>
>
Thanks for the review.



-- 
Shine bright,
(: Nav :)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v4] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
  2013-10-11  8:23 ` [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible Naveen Krishna Chatradhi
  2013-10-11 14:30   ` Lars-Peter Clausen
@ 2013-10-15  5:15   ` Naveen Krishna Chatradhi
  2013-10-25 15:42     ` Doug Anderson
  2013-10-28  5:41   ` [PATCH v5] " Naveen Krishna Chatradhi
  2013-11-05  9:45   ` [PATCH v6] " Naveen Krishna Chatradhi
  3 siblings, 1 reply; 8+ messages in thread
From: Naveen Krishna Chatradhi @ 2013-10-15  5:15 UTC (permalink / raw)
  To: linux-iio
  Cc: linux-kernel, linux-samsung-soc, dianders, gregkh,
	naveenkrishna.ch, lars, cpgs

This patch does the following
1. The irq routine is so simple (just one register read) shouldn't be long
   Hence, reduce the timeout to 100milli secs,
2. With 100ms of wait time, interruptible is very much unnecessary.
   Hence, use wait_for_completion_timeout instead of
   wait_for_completion_interruptible_timeout
3. Reset software if a timeout happens.
4. Add INIT_COMPLETION before the wait_for_completion_timeout in raw_read()

Note: submitted for review at https://patchwork.kernel.org/patch/2279591/

Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Cc: Doug Anderson <dianders@chromium.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes since v1:
As per discussion at
http://marc.info/?l=linux-kernel&m=136517637228869&w=3

Changes since v2:
None.
Rebased and reposting.

Changes since v3:
1. commit message change and
2. removed an unncessary assignment

 drivers/iio/adc/exynos_adc.c |   69 +++++++++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 31 deletions(-)

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index d25b262..ac25e3e 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -82,7 +82,7 @@ enum adc_version {
 #define ADC_CON_EN_START	(1u << 0)
 #define ADC_DATX_MASK		0xFFF
 
-#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(1000))
+#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(100))
 
 struct exynos_adc {
 	void __iomem		*regs;
@@ -112,6 +112,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
 	return (unsigned int)match->data;
 }
 
+static void exynos_adc_hw_init(struct exynos_adc *info)
+{
+	u32 con1, con2;
+
+	if (info->version == ADC_V2) {
+		con1 = ADC_V2_CON1_SOFT_RESET;
+		writel(con1, ADC_V2_CON1(info->regs));
+
+		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+		writel(con2, ADC_V2_CON2(info->regs));
+
+		/* Enable interrupts */
+		writel(1, ADC_V2_INT_EN(info->regs));
+	} else {
+		/* set default prescaler values and Enable prescaler */
+		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+		/* Enable 12-bit ADC resolution */
+		con1 |= ADC_V1_CON_RES;
+		writel(con1, ADC_V1_CON(info->regs));
+	}
+}
+
 static int exynos_read_raw(struct iio_dev *indio_dev,
 				struct iio_chan_spec const *chan,
 				int *val,
@@ -121,6 +145,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 	struct exynos_adc *info = iio_priv(indio_dev);
 	unsigned long timeout;
 	u32 con1, con2;
+	int ret;
 
 	if (mask != IIO_CHAN_INFO_RAW)
 		return -EINVAL;
@@ -145,16 +170,22 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 				ADC_V1_CON(info->regs));
 	}
 
-	timeout = wait_for_completion_interruptible_timeout
+	INIT_COMPLETION(info->completion);
+
+	timeout = wait_for_completion_timeout
 			(&info->completion, EXYNOS_ADC_TIMEOUT);
-	*val = info->value;
+	if (timeout == 0) {
+		dev_warn(&indio_dev->dev, "Conversion timed out reseting\n");
+		exynos_adc_hw_init(info);
+		ret = -ETIMEDOUT;
+	} else {
+		*val = info->value;
+		ret = IIO_VAL_INT;
+	}
 
 	mutex_unlock(&indio_dev->mlock);
 
-	if (timeout == 0)
-		return -ETIMEDOUT;
-
-	return IIO_VAL_INT;
+	return ret;
 }
 
 static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
@@ -226,30 +257,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
 	return 0;
 }
 
-static void exynos_adc_hw_init(struct exynos_adc *info)
-{
-	u32 con1, con2;
-
-	if (info->version == ADC_V2) {
-		con1 = ADC_V2_CON1_SOFT_RESET;
-		writel(con1, ADC_V2_CON1(info->regs));
-
-		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
-			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
-		writel(con2, ADC_V2_CON2(info->regs));
-
-		/* Enable interrupts */
-		writel(1, ADC_V2_INT_EN(info->regs));
-	} else {
-		/* set default prescaler values and Enable prescaler */
-		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
-
-		/* Enable 12-bit ADC resolution */
-		con1 |= ADC_V1_CON_RES;
-		writel(con1, ADC_V1_CON(info->regs));
-	}
-}
-
 static int exynos_adc_probe(struct platform_device *pdev)
 {
 	struct exynos_adc *info = NULL;
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
  2013-10-15  5:15   ` [PATCH v4] " Naveen Krishna Chatradhi
@ 2013-10-25 15:42     ` Doug Anderson
  0 siblings, 0 replies; 8+ messages in thread
From: Doug Anderson @ 2013-10-25 15:42 UTC (permalink / raw)
  To: Naveen Krishna Chatradhi, Grant Grundler
  Cc: linux-iio, linux-kernel, linux-samsung-soc, Greg Kroah-Hartman,
	Naveen Krishna, Lars-Peter Clausen, cpgs .

Naveen,

On Mon, Oct 14, 2013 at 10:15 PM, Naveen Krishna Chatradhi
<ch.naveen@samsung.com> wrote:
> This patch does the following
> 1. The irq routine is so simple (just one register read) shouldn't be long
>    Hence, reduce the timeout to 100milli secs,
> 2. With 100ms of wait time, interruptible is very much unnecessary.
>    Hence, use wait_for_completion_timeout instead of
>    wait_for_completion_interruptible_timeout
> 3. Reset software if a timeout happens.
> 4. Add INIT_COMPLETION before the wait_for_completion_timeout in raw_read()
>
> Note: submitted for review at https://patchwork.kernel.org/patch/2279591/
>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Cc: Doug Anderson <dianders@chromium.org>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> ---
> Changes since v1:
> As per discussion at
> http://marc.info/?l=linux-kernel&m=136517637228869&w=3
>
> Changes since v2:
> None.
> Rebased and reposting.
>
> Changes since v3:
> 1. commit message change and
> 2. removed an unncessary assignment
>
>  drivers/iio/adc/exynos_adc.c |   69 +++++++++++++++++++++++-------------------
>  1 file changed, 38 insertions(+), 31 deletions(-)

Please spin to match the changes that Grant requested on our gerrit at
<https://chromium-review.googlesource.com/172724>.  Thanks!  :)

-Doug

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v5] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
  2013-10-11  8:23 ` [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible Naveen Krishna Chatradhi
  2013-10-11 14:30   ` Lars-Peter Clausen
  2013-10-15  5:15   ` [PATCH v4] " Naveen Krishna Chatradhi
@ 2013-10-28  5:41   ` Naveen Krishna Chatradhi
  2013-11-05  9:45   ` [PATCH v6] " Naveen Krishna Chatradhi
  3 siblings, 0 replies; 8+ messages in thread
From: Naveen Krishna Chatradhi @ 2013-10-28  5:41 UTC (permalink / raw)
  To: linux-iio
  Cc: linux-kernel, linux-samsung-soc, dianders, gregkh,
	naveenkrishna.ch, lars, grundler, cpgs

1. The irq routine is so simple (just one register read) shouldn't be long
   Hence, reduce the timeout to 100milli secs,
2. With 100ms of wait time, interruptible is very much unnecessary.
   Hence, use wait_for_completion_timeout instead of
   wait_for_completion_interruptible_timeout
3. Reset software if a timeout happens.
4. Add INIT_COMPLETION before the wait_for_completion_timeout in raw_read()

Note: submitted for review at https://patchwork.kernel.org/patch/2279591/

Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Cc: Doug Anderson <dianders@chromium.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Reviewed-on: https://chromium-review.googlesource.com/172724
Reviewed-by: Doug Anderson <dianders@chromium.org>
---
Changes since v1:
As per discussion at
http://marc.info/?l=linux-kernel&m=136517637228869&w=3

Changes since v2:
None.
Rebased and reposting.

Changes since v3:
1. commit message change and
2. removed an unncessary assignment

Changes since v4:
Moved INIT_COMPLETION call to the starting of the function


 drivers/iio/adc/exynos_adc.c | 69 ++++++++++++++++++++++++--------------------
 1 file changed, 38 insertions(+), 31 deletions(-)

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 0f2ca60..a675751 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -81,7 +81,7 @@ enum adc_version {
 #define ADC_CON_EN_START	(1u << 0)
 #define ADC_DATX_MASK		0xFFF
 
-#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(1000))
+#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(100))
 
 struct exynos_adc {
 	void __iomem		*regs;
@@ -111,6 +111,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
 	return (unsigned int)match->data;
 }
 
+static void exynos_adc_hw_init(struct exynos_adc *info)
+{
+	u32 con1, con2;
+
+	if (info->version == ADC_V2) {
+		con1 = ADC_V2_CON1_SOFT_RESET;
+		writel(con1, ADC_V2_CON1(info->regs));
+
+		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+		writel(con2, ADC_V2_CON2(info->regs));
+
+		/* Enable interrupts */
+		writel(1, ADC_V2_INT_EN(info->regs));
+	} else {
+		/* set default prescaler values and Enable prescaler */
+		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+		/* Enable 12-bit ADC resolution */
+		con1 |= ADC_V1_CON_RES;
+		writel(con1, ADC_V1_CON(info->regs));
+	}
+}
+
 static int exynos_read_raw(struct iio_dev *indio_dev,
 				struct iio_chan_spec const *chan,
 				int *val,
@@ -120,11 +144,13 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 	struct exynos_adc *info = iio_priv(indio_dev);
 	unsigned long timeout;
 	u32 con1, con2;
+	int ret;
 
 	if (mask != IIO_CHAN_INFO_RAW)
 		return -EINVAL;
 
 	mutex_lock(&indio_dev->mlock);
+	INIT_COMPLETION(info->completion);
 
 	/* Select the channel to be used and Trigger conversion */
 	if (info->version == ADC_V2) {
@@ -144,16 +170,21 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 				ADC_V1_CON(info->regs));
 	}
 
-	timeout = wait_for_completion_interruptible_timeout
+	timeout = wait_for_completion_timeout
 			(&info->completion, EXYNOS_ADC_TIMEOUT);
-	*val = info->value;
+	if (timeout == 0) {
+		dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
+		exynos_adc_hw_init(info);
+		ret = -ETIMEDOUT;
+	} else {
+		*val = info->value;
+		*val2 = 0;
+		ret = IIO_VAL_INT;
+	}
 
 	mutex_unlock(&indio_dev->mlock);
 
-	if (timeout == 0)
-		return -ETIMEDOUT;
-
-	return IIO_VAL_INT;
+	return ret;
 }
 
 static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
@@ -225,30 +256,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
 	return 0;
 }
 
-static void exynos_adc_hw_init(struct exynos_adc *info)
-{
-	u32 con1, con2;
-
-	if (info->version == ADC_V2) {
-		con1 = ADC_V2_CON1_SOFT_RESET;
-		writel(con1, ADC_V2_CON1(info->regs));
-
-		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
-			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
-		writel(con2, ADC_V2_CON2(info->regs));
-
-		/* Enable interrupts */
-		writel(1, ADC_V2_INT_EN(info->regs));
-	} else {
-		/* set default prescaler values and Enable prescaler */
-		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
-
-		/* Enable 12-bit ADC resolution */
-		con1 |= ADC_V1_CON_RES;
-		writel(con1, ADC_V1_CON(info->regs));
-	}
-}
-
 static int exynos_adc_probe(struct platform_device *pdev)
 {
 	struct exynos_adc *info = NULL;
-- 
1.7.12.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v6] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
  2013-10-11  8:23 ` [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible Naveen Krishna Chatradhi
                     ` (2 preceding siblings ...)
  2013-10-28  5:41   ` [PATCH v5] " Naveen Krishna Chatradhi
@ 2013-11-05  9:45   ` Naveen Krishna Chatradhi
  2013-11-10 12:48     ` Tomasz Figa
  3 siblings, 1 reply; 8+ messages in thread
From: Naveen Krishna Chatradhi @ 2013-11-05  9:45 UTC (permalink / raw)
  To: linux-iio
  Cc: linux-kernel, linux-samsung-soc, dianders, gregkh,
	naveenkrishna.ch, lars, grundler, cpgs

1. The irq routine is so simple (just one register read) shouldn't be long
   Hence, reduce the timeout to 100milli secs,
2. With 100ms of wait time, interruptible is very much unnecessary.
   Hence, use wait_for_completion_timeout instead of
   wait_for_completion_interruptible_timeout
3. Reset software if a timeout happens.
4. Add reinit_completion() before the wait_for_completion_timeout in raw_read()

Note: submitted for review at https://patchwork.kernel.org/patch/2279591/

Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Cc: Doug Anderson <dianders@chromium.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Reviewed-on: https://chromium-review.googlesource.com/172724
Reviewed-by: Doug Anderson <dianders@chromium.org>
---
Changes since v1:
As per discussion at
http://marc.info/?l=linux-kernel&m=136517637228869&w=3

Changes since v2:
None.
Rebased and reposting.

Changes since v3:
1. commit message change and
2. removed an unncessary assignment

Changes since v4:
Moved INIT_COMPLETION call to the starting of the function

Changes since v5:
INIT_COMPLETION was replaced by reinit_completion
("tree-wide: use reinit_completion instead of INIT_COMPLETION").
Use it to avoid the following build error:
undefined identifier 'INIT_COMPLETION'


 drivers/iio/adc/exynos_adc.c | 69 ++++++++++++++++++++++++--------------------
 1 file changed, 38 insertions(+), 31 deletions(-)

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 0f2ca60..a675751 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -81,7 +81,7 @@ enum adc_version {
 #define ADC_CON_EN_START	(1u << 0)
 #define ADC_DATX_MASK		0xFFF
 
-#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(1000))
+#define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(100))
 
 struct exynos_adc {
 	void __iomem		*regs;
@@ -111,6 +111,30 @@ static inline unsigned int exynos_adc_get_version(struct platform_device *pdev)
 	return (unsigned int)match->data;
 }
 
+static void exynos_adc_hw_init(struct exynos_adc *info)
+{
+	u32 con1, con2;
+
+	if (info->version == ADC_V2) {
+		con1 = ADC_V2_CON1_SOFT_RESET;
+		writel(con1, ADC_V2_CON1(info->regs));
+
+		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
+			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
+		writel(con2, ADC_V2_CON2(info->regs));
+
+		/* Enable interrupts */
+		writel(1, ADC_V2_INT_EN(info->regs));
+	} else {
+		/* set default prescaler values and Enable prescaler */
+		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
+
+		/* Enable 12-bit ADC resolution */
+		con1 |= ADC_V1_CON_RES;
+		writel(con1, ADC_V1_CON(info->regs));
+	}
+}
+
 static int exynos_read_raw(struct iio_dev *indio_dev,
 				struct iio_chan_spec const *chan,
 				int *val,
@@ -120,11 +144,13 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 	struct exynos_adc *info = iio_priv(indio_dev);
 	unsigned long timeout;
 	u32 con1, con2;
+	int ret;
 
 	if (mask != IIO_CHAN_INFO_RAW)
 		return -EINVAL;
 
 	mutex_lock(&indio_dev->mlock);
+	reinit_completion(&info->completion);
 
 	/* Select the channel to be used and Trigger conversion */
 	if (info->version == ADC_V2) {
@@ -144,16 +170,21 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 				ADC_V1_CON(info->regs));
 	}
 
-	timeout = wait_for_completion_interruptible_timeout
+	timeout = wait_for_completion_timeout
 			(&info->completion, EXYNOS_ADC_TIMEOUT);
-	*val = info->value;
+	if (timeout == 0) {
+		dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
+		exynos_adc_hw_init(info);
+		ret = -ETIMEDOUT;
+	} else {
+		*val = info->value;
+		*val2 = 0;
+		ret = IIO_VAL_INT;
+	}
 
 	mutex_unlock(&indio_dev->mlock);
 
-	if (timeout == 0)
-		return -ETIMEDOUT;
-
-	return IIO_VAL_INT;
+	return ret;
 }
 
 static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
@@ -225,30 +256,6 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
 	return 0;
 }
 
-static void exynos_adc_hw_init(struct exynos_adc *info)
-{
-	u32 con1, con2;
-
-	if (info->version == ADC_V2) {
-		con1 = ADC_V2_CON1_SOFT_RESET;
-		writel(con1, ADC_V2_CON1(info->regs));
-
-		con2 = ADC_V2_CON2_OSEL | ADC_V2_CON2_ESEL |
-			ADC_V2_CON2_HIGHF | ADC_V2_CON2_C_TIME(0);
-		writel(con2, ADC_V2_CON2(info->regs));
-
-		/* Enable interrupts */
-		writel(1, ADC_V2_INT_EN(info->regs));
-	} else {
-		/* set default prescaler values and Enable prescaler */
-		con1 =  ADC_V1_CON_PRSCLV(49) | ADC_V1_CON_PRSCEN;
-
-		/* Enable 12-bit ADC resolution */
-		con1 |= ADC_V1_CON_RES;
-		writel(con1, ADC_V1_CON(info->regs));
-	}
-}
-
 static int exynos_adc_probe(struct platform_device *pdev)
 {
 	struct exynos_adc *info = NULL;
-- 
1.7.12.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v6] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible
  2013-11-05  9:45   ` [PATCH v6] " Naveen Krishna Chatradhi
@ 2013-11-10 12:48     ` Tomasz Figa
  0 siblings, 0 replies; 8+ messages in thread
From: Tomasz Figa @ 2013-11-10 12:48 UTC (permalink / raw)
  To: Naveen Krishna Chatradhi
  Cc: linux-iio, linux-kernel, linux-samsung-soc, dianders, gregkh,
	naveenkrishna.ch, lars, grundler, cpgs

Hi Naveen,

On Tuesday 05 of November 2013 15:15:30 Naveen Krishna Chatradhi wrote:
> 1. The irq routine is so simple (just one register read) shouldn't be
> long Hence, reduce the timeout to 100milli secs,

I believe that the timeout value depends mostly on maximum conversion time 
and interrupt handler complexity is not very significant here.

> 2. With 100ms of wait time, interruptible is very much unnecessary.
>    Hence, use wait_for_completion_timeout instead of
>    wait_for_completion_interruptible_timeout
> 3. Reset software if a timeout happens.
> 4. Add reinit_completion() before the wait_for_completion_timeout in
> raw_read()

All the four points listed above, even just by the form they are written 
in, suggest that they should be separate four patches.

In addition, patch description should explain why such change is needed, 
i.e. what it fixes, improves or prepares the code for.

> Note: submitted for review at
> https://patchwork.kernel.org/patch/2279591/
> 

This should not be located in patch description, but rather in comments 
section below, as is the change log.

> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Cc: Doug Anderson <dianders@chromium.org>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Reviewed-on: https://chromium-review.googlesource.com/172724
> Reviewed-by: Doug Anderson <dianders@chromium.org>
> ---
> Changes since v1:
> As per discussion at
> http://marc.info/?l=linux-kernel&m=136517637228869&w=3
> 
> Changes since v2:
> None.
> Rebased and reposting.
> 
> Changes since v3:
> 1. commit message change and
> 2. removed an unncessary assignment
> 
> Changes since v4:
> Moved INIT_COMPLETION call to the starting of the function
> 
> Changes since v5:
> INIT_COMPLETION was replaced by reinit_completion
> ("tree-wide: use reinit_completion instead of INIT_COMPLETION").
> Use it to avoid the following build error:
> undefined identifier 'INIT_COMPLETION'

Not really a comment to the patch, but rather a suggestion for future:

It is more convenient to read the change log if it goes from newest to 
oldest order.

Otherwise the changes alone look good.

Best regards,
Tomasz


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-11-10 12:48 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1365048389-6364-1-git-send-email-naveenkrishna.ch@gmail.com>
2013-10-11  8:23 ` [PATCH v3] iio: exynos_adc: use wait_for_completion_timeout instead of interruptible Naveen Krishna Chatradhi
2013-10-11 14:30   ` Lars-Peter Clausen
2013-10-12  6:40     ` Naveen Krishna Ch
2013-10-15  5:15   ` [PATCH v4] " Naveen Krishna Chatradhi
2013-10-25 15:42     ` Doug Anderson
2013-10-28  5:41   ` [PATCH v5] " Naveen Krishna Chatradhi
2013-11-05  9:45   ` [PATCH v6] " Naveen Krishna Chatradhi
2013-11-10 12:48     ` Tomasz Figa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).