patch "iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access" added to staging-linus
Subsystems (2)
This is a note to let you know that I've just added the patch titled
iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access
to my staging git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
in the staging-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
Quoted 1 line
From
90c43ec6997a892448f1f86180a515f59cafd8a3Mon Sep 17 00:00:00 2001
From: Vignesh R <[email protected]>
Date: Wed, 17 Aug 2016 17:43:00 +0530
Subject: iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access
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.
--- drivers/iio/adc/ti_am335x_adc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/iio/adc/ti_am335x_adc.c +11 -3
@@ -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 )
Signature · 1 line
2.9.3