Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1457706 > unrolled thread
| Started by | Vignesh R <vigneshr@ti.com> |
|---|---|
| First post | 2016-08-08 13:10 +0200 |
| Last post | 2016-08-09 12:00 +0200 |
| Articles | 4 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/2] ADC: Fix bugs related to oneshot read Vignesh R <vigneshr@ti.com> - 2016-08-08 13:10 +0200
[PATCH 1/2] iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access Vignesh R <vigneshr@ti.com> - 2016-08-08 13:10 +0200
Re: [PATCH 1/2] iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access Matt Ranostay <mranostay@gmail.com> - 2016-08-09 12:00 +0200
Re: [PATCH 1/2] iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access Vignesh R <vigneshr@ti.com> - 2016-08-09 12:00 +0200
| From | Vignesh R <vigneshr@ti.com> |
|---|---|
| Date | 2016-08-08 13:10 +0200 |
| Subject | [PATCH 0/2] ADC: Fix bugs related to oneshot read |
| Message-ID | <s3QBs-A4-9@gated-at.bofh.it> |
This series fixes a couple of bugs related to simultaneous read of multiple ADC channels in oneshot mode. Since, all channels share FIFO1, it has to be protected using a mutex, implemented by patch 1. Patch 2 increases the timeout waiting for a ADC sample. Vignesh R (2): iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access iio: adc: ti_am335x_adc: Increase timeout value waiting for ADC sample drivers/iio/adc/ti_am335x_adc.c | 16 ++++++++++++---- include/linux/mfd/ti_am335x_tscadc.h | 8 ++++---- 2 files changed, 16 insertions(+), 8 deletions(-) -- 2.9.2
[toc] | [next] | [standalone]
| From | Vignesh R <vigneshr@ti.com> |
|---|---|
| Date | 2016-08-08 13:10 +0200 |
| Subject | [PATCH 1/2] iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access |
| Message-ID | <s3QBs-A4-23@gated-at.bofh.it> |
| In reply to | #1457706 |
It is possible that two or more ADC channels can be simultaneously
requested for raw samples, in which case there can be race in access to
FIFO data resulting in loss of samples.
If am335x_tsc_se_set_once() is called again from tiadc_read_raw(), when
ADC is still acquired to sample one of the channels, the second process
might be put into uninterruptible sleep state. Fix these issues, by
protecting FIFO access and channel configurations with a mutex. Since
tiadc_read_raw() might take anywhere between few microseconds to few
milliseconds to finish execution (depending on averaging and delay
values supplied via DT), its better to use mutex instead of spinlock.
Signed-off-by: Vignesh R <vigneshr@ti.com>
---
drivers/iio/adc/ti_am335x_adc.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 8a368756881b..bed9977a1863 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -32,6 +32,7 @@
struct tiadc_device {
struct ti_tscadc_dev *mfd_tscadc;
+ struct mutex fifo1_lock; /* to protect fifo access */
int channels;
u8 channel_line[8];
u8 channel_step[8];
@@ -359,6 +360,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ int ret = IIO_VAL_INT;
int i, map_val;
unsigned int fifo1count, read, stepid;
bool found = false;
@@ -372,6 +374,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
if (!step_en)
return -EINVAL;
+ mutex_lock(&adc_dev->fifo1_lock);
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
while (fifo1count--)
tiadc_readl(adc_dev, REG_FIFO1);
@@ -388,7 +391,8 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
if (time_after(jiffies, timeout)) {
am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
- return -EAGAIN;
+ ret = -EAGAIN;
+ goto err_unlock;
}
}
map_val = adc_dev->channel_step[chan->scan_index];
@@ -414,8 +418,11 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
if (found == false)
- return -EBUSY;
- return IIO_VAL_INT;
+ ret = -EBUSY;
+
+err_unlock:
+ mutex_unlock(&adc_dev->fifo1_lock);
+ return ret;
}
static const struct iio_info tiadc_info = {
@@ -483,6 +490,7 @@ static int tiadc_probe(struct platform_device *pdev)
tiadc_step_config(indio_dev);
tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
+ mutex_init(&adc_dev->fifo1_lock);
err = tiadc_channel_init(indio_dev, adc_dev->channels);
if (err < 0)
--
2.9.2
[toc] | [prev] | [next] | [standalone]
| From | Matt Ranostay <mranostay@gmail.com> |
|---|---|
| Date | 2016-08-09 12:00 +0200 |
| Subject | Re: [PATCH 1/2] iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access |
| Message-ID | <s4bZf-5Sz-1@gated-at.bofh.it> |
| In reply to | #1457708 |
On Mon, Aug 8, 2016 at 4:05 AM, Vignesh R <vigneshr@ti.com> wrote:
> It is possible that two or more ADC channels can be simultaneously
> requested for raw samples, in which case there can be race in access to
> FIFO data resulting in loss of samples.
> If am335x_tsc_se_set_once() is called again from tiadc_read_raw(), when
> ADC is still acquired to sample one of the channels, the second process
> might be put into uninterruptible sleep state. Fix these issues, by
> protecting FIFO access and channel configurations with a mutex. Since
> tiadc_read_raw() might take anywhere between few microseconds to few
> milliseconds to finish execution (depending on averaging and delay
> values supplied via DT), its better to use mutex instead of spinlock.
>
> Signed-off-by: Vignesh R <vigneshr@ti.com>
> ---
> drivers/iio/adc/ti_am335x_adc.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index 8a368756881b..bed9977a1863 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -32,6 +32,7 @@
>
> struct tiadc_device {
> struct ti_tscadc_dev *mfd_tscadc;
> + struct mutex fifo1_lock; /* to protect fifo access */
Are there more than one FIFOs, or even possible? Just wondering the
number indexing here..
> int channels;
> u8 channel_line[8];
> u8 channel_step[8];
> @@ -359,6 +360,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
> int *val, int *val2, long mask)
> {
> struct tiadc_device *adc_dev = iio_priv(indio_dev);
> + int ret = IIO_VAL_INT;
> int i, map_val;
> unsigned int fifo1count, read, stepid;
> bool found = false;
> @@ -372,6 +374,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
> if (!step_en)
> return -EINVAL;
>
> + mutex_lock(&adc_dev->fifo1_lock);
> fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> while (fifo1count--)
> tiadc_readl(adc_dev, REG_FIFO1);
> @@ -388,7 +391,8 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
>
> if (time_after(jiffies, timeout)) {
> am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
> - return -EAGAIN;
> + ret = -EAGAIN;
> + goto err_unlock;
> }
> }
> map_val = adc_dev->channel_step[chan->scan_index];
> @@ -414,8 +418,11 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
> am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
>
> if (found == false)
> - return -EBUSY;
> - return IIO_VAL_INT;
> + ret = -EBUSY;
> +
> +err_unlock:
> + mutex_unlock(&adc_dev->fifo1_lock);
> + return ret;
> }
>
> static const struct iio_info tiadc_info = {
> @@ -483,6 +490,7 @@ static int tiadc_probe(struct platform_device *pdev)
>
> tiadc_step_config(indio_dev);
> tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
> + mutex_init(&adc_dev->fifo1_lock);
>
> err = tiadc_channel_init(indio_dev, adc_dev->channels);
> if (err < 0)
> --
> 2.9.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
[toc] | [prev] | [next] | [standalone]
| From | Vignesh R <vigneshr@ti.com> |
|---|---|
| Date | 2016-08-09 12:00 +0200 |
| Subject | Re: [PATCH 1/2] iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access |
| Message-ID | <s4bZf-5Sz-5@gated-at.bofh.it> |
| In reply to | #1458554 |
On Tuesday 09 August 2016 03:21 PM, Matt Ranostay wrote:
> On Mon, Aug 8, 2016 at 4:05 AM, Vignesh R <vigneshr@ti.com> wrote:
>> It is possible that two or more ADC channels can be simultaneously
>> requested for raw samples, in which case there can be race in access to
>> FIFO data resulting in loss of samples.
>> If am335x_tsc_se_set_once() is called again from tiadc_read_raw(), when
>> ADC is still acquired to sample one of the channels, the second process
>> might be put into uninterruptible sleep state. Fix these issues, by
>> protecting FIFO access and channel configurations with a mutex. Since
>> tiadc_read_raw() might take anywhere between few microseconds to few
>> milliseconds to finish execution (depending on averaging and delay
>> values supplied via DT), its better to use mutex instead of spinlock.
>>
>> Signed-off-by: Vignesh R <vigneshr@ti.com>
>> ---
>> drivers/iio/adc/ti_am335x_adc.c | 14 +++++++++++---
>> 1 file changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>> index 8a368756881b..bed9977a1863 100644
>> --- a/drivers/iio/adc/ti_am335x_adc.c
>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> @@ -32,6 +32,7 @@
>>
>> struct tiadc_device {
>> struct ti_tscadc_dev *mfd_tscadc;
>> + struct mutex fifo1_lock; /* to protect fifo access */
>
> Are there more than one FIFOs, or even possible? Just wondering the
> number indexing here..
ADC IP as such as two FIFOs: FIFO0 and FIFO1. FIFO0 is dedicated for
touchscreen channels and FIFO1 is used for ADC channels. Its not
possible to use FIFO0 for ADC, but to match h/w register naming, I used
above name for mutex.
--
Regards
Vignesh
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web