lkml.org 
[lkml]   [2016]   [Sep]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.7 070/184] iio: adc: ti_am335x_adc: Protect FIFO1 from concurrent access
    Date
    4.7-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Vignesh R <vigneshr@ti.com>

    commit 90c43ec6997a892448f1f86180a515f59cafd8a3 upstream.

    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.

    Fixes: 7ca6740cd1cd4 ("mfd: input: iio: ti_amm335x: Rework TSC/ADC synchronization")
    Signed-off-by: Vignesh R <vigneshr@ti.com>
    Signed-off-by: Jonathan Cameron <jic23@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/iio/adc/ti_am335x_adc.c | 14 +++++++++++---
    1 file changed, 11 insertions(+), 3 deletions(-)

    --- 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];
    @@ -360,6 +361,7 @@ static int tiadc_read_raw(struct iio_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;
    @@ -373,6 +375,7 @@ static int tiadc_read_raw(struct iio_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);
    @@ -389,7 +392,8 @@ static int tiadc_read_raw(struct iio_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];
    @@ -415,8 +419,11 @@ static int tiadc_read_raw(struct iio_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 = {
    @@ -485,6 +492,7 @@ static int tiadc_probe(struct platform_d

    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)

    \
     
     \ /
      Last update: 2016-09-23 00:04    [W:7.849 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site