summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorSang-Hun Lee <sanlee@nvidia.com>2014-05-17 18:34:48 -0700
committerRiham Haidar <rhaidar@nvidia.com>2014-05-23 22:36:00 -0700
commit830db980d3a6e76ffcde8d588a8b6ef487e26283 (patch)
treea03c01f3c874c5327ddadc59cf380cb3bf4c0e86 /drivers/staging
parent87839a56e4a1537e4af0bfdd6eeb26389fc3d7c2 (diff)
iio: adc: palmas: disallow access post-shutdown
- 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 Reviewed-by: Riham Haidar <rhaidar@nvidia.com> Tested-by: Riham Haidar <rhaidar@nvidia.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/iio/adc/palmas_gpadc.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/staging/iio/adc/palmas_gpadc.c b/drivers/staging/iio/adc/palmas_gpadc.c
index eec770fd1459..dc2e03fd2a48 100644
--- a/drivers/staging/iio/adc/palmas_gpadc.c
+++ b/drivers/staging/iio/adc/palmas_gpadc.c
@@ -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;
};
/*
@@ -586,8 +589,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:
@@ -664,11 +672,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;
}
@@ -1055,6 +1065,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,
@@ -1207,8 +1220,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