]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
iio: adc: palmas: disallow access post-shutdown
authorSang-Hun Lee <sanlee@nvidia.com>
Sun, 18 May 2014 01:34:48 +0000 (18:34 -0700)
committerSimone Willett <swillett@nvidia.com>
Wed, 4 Jun 2014 17:18:29 +0000 (10:18 -0700)
 - Once the shutdown has been called, any access to
   i2c needs to be disallowed to avoid a race

Bug 1510778

Change-Id: I93cc1ec4cdadfe2084b6aa5a8bc9d2b6cf56e879
Signed-off-by: Sang-Hun Lee <sanlee@nvidia.com>
Reviewed-on: http://git-master/r/411189
(cherry picked from commit 830db980d3a6e76ffcde8d588a8b6ef487e26283)
Reviewed-on: http://git-master/r/416327
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Mitch Luban <mluban@nvidia.com>
drivers/staging/iio/adc/palmas_gpadc.c

index 9ae66f6e7b6f9ea3316485fc1cc69a816c24fc42..f726f483d7094fd5016c52b9f254631d083325aa 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
+#include <linux/mutex.h>
 
 #define MOD_NAME               "palmas-gpadc"
 #define ADC_CONVERTION_TIMEOUT (msecs_to_jiffies(5000))
@@ -103,6 +104,8 @@ struct palmas_gpadc {
        int                             auto_conversion_period;
 
        struct dentry                   *dentry;
+       bool is_shutdown;
+       struct mutex lock;
 };
 
 /*
@@ -599,8 +602,13 @@ static int palmas_gpadc_read_raw(struct iio_dev *indio_dev,
        if (adc_chan > PALMAS_ADC_CH_MAX)
                return -EINVAL;
 
-       mutex_lock(&indio_dev->mlock);
+       mutex_lock(&adc->lock);
+       if (adc->is_shutdown) {
+               mutex_unlock(&adc->lock);
+               return -EINVAL;
+       }
 
+       mutex_lock(&indio_dev->mlock);
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
        case IIO_CHAN_INFO_PROCESSED:
@@ -672,11 +680,13 @@ static int palmas_gpadc_read_raw(struct iio_dev *indio_dev,
        }
 
        mutex_unlock(&indio_dev->mlock);
+       mutex_unlock(&adc->lock);
        return ret;
 
 out:
        palmas_gpadc_read_done(adc, adc_chan);
        mutex_unlock(&indio_dev->mlock);
+       mutex_unlock(&adc->lock);
        return ret;
 }
 
@@ -1123,6 +1133,9 @@ static int palmas_gpadc_probe(struct platform_device *pdev)
        init_completion(&adc->conv_completion);
        dev_set_drvdata(&pdev->dev, iodev);
 
+       adc->is_shutdown = false;
+       mutex_init(&adc->lock);
+
        adc->auto_conversion_period = gpadc_pdata->auto_conversion_period_ms;
        adc->irq = palmas_irq_get_virq(adc->palmas, PALMAS_GPADC_EOC_SW_IRQ);
        ret = request_threaded_irq(adc->irq, NULL,
@@ -1283,8 +1296,11 @@ static void palmas_gpadc_shutdown(struct platform_device *pdev)
        struct iio_dev *iodev = dev_get_drvdata(&pdev->dev);
        struct palmas_gpadc *adc = iio_priv(iodev);
 
+       mutex_lock(&adc->lock);
+       adc->is_shutdown = true;
        if (adc->auto_conv0_enable || adc->auto_conv1_enable)
                palmas_gpadc_auto_conv_reset(adc);
+       mutex_unlock(&adc->lock);
 }
 
 #ifdef CONFIG_PM_SLEEP