summaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-sprd.c
diff options
context:
space:
mode:
authorBaolin Wang <baolin.wang@linaro.org>2018-04-09 08:40:54 +0200
committerWolfram Sang <wsa@the-dreams.de>2018-04-27 14:12:17 +0200
commitda33aa03fa34c918faf2c371ebda0dd961d7ccb2 (patch)
treee84cbc68a2d68b3dc2afb61e62e6a9bdc9852173 /drivers/i2c/busses/i2c-sprd.c
parenti2c: dev: prevent ZERO_SIZE_PTR deref in i2cdev_ioctl_rdwr() (diff)
downloadlinux-da33aa03fa34c918faf2c371ebda0dd961d7ccb2.tar.xz
linux-da33aa03fa34c918faf2c371ebda0dd961d7ccb2.zip
i2c: sprd: Prevent i2c accesses after suspend is called
Add one flag to indicate if the i2c controller has been in suspend state, which can prevent i2c accesses after i2c controller is suspended following system suspend. Signed-off-by: Baolin Wang <baolin.wang@linaro.org> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/busses/i2c-sprd.c')
-rw-r--r--drivers/i2c/busses/i2c-sprd.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c
index 25fcc3c1e32b..2fdad63a23a1 100644
--- a/drivers/i2c/busses/i2c-sprd.c
+++ b/drivers/i2c/busses/i2c-sprd.c
@@ -86,6 +86,7 @@ struct sprd_i2c {
u32 count;
int irq;
int err;
+ bool is_suspended;
};
static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count)
@@ -283,6 +284,9 @@ static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap,
struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
int im, ret;
+ if (i2c_dev->is_suspended)
+ return -EBUSY;
+
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0)
return ret;
@@ -586,11 +590,23 @@ static int sprd_i2c_remove(struct platform_device *pdev)
static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev)
{
+ struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
+
+ i2c_lock_adapter(&i2c_dev->adap);
+ i2c_dev->is_suspended = true;
+ i2c_unlock_adapter(&i2c_dev->adap);
+
return pm_runtime_force_suspend(pdev);
}
static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev)
{
+ struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
+
+ i2c_lock_adapter(&i2c_dev->adap);
+ i2c_dev->is_suspended = false;
+ i2c_unlock_adapter(&i2c_dev->adap);
+
return pm_runtime_force_resume(pdev);
}