summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorHaibo Chen <haibo.chen@nxp.com>2022-08-31 18:37:35 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-08 12:28:05 +0200
commit111a3586ed4a6ee15e467e58c9208152d469f430 (patch)
treeda2b14d923ea2f5287fbdee348e5b38fca3f990a /drivers/gpio
parent53196e0376205ed49b75bfd0475af5e0fbd20156 (diff)
gpio: pca953x: Add mutex_lock for regcache sync in PM
[ Upstream commit 518e26f11af2fe4f5bebf9a0351595d508c7077f ] The regcache sync will set the cache_bypass = true, at that time, when there is regmap write operation, it will bypass the regmap cache, then the regcache sync will write back the value from cache to register, which is not as our expectation. Though regmap already use its internal lock to avoid such issue, but this driver force disable the regmap internal lock in its regmap config: disable_locking = true To avoid this issue, use the driver's own lock to do the protect in system PM. Fixes: b76574300504 ("gpio: pca953x: Restore registers after suspend/resume cycle") Signed-off-by: Haibo Chen <haibo.chen@nxp.com> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-pca953x.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 64befd6f702b..4860bf3b7e00 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -1163,7 +1163,9 @@ static int pca953x_suspend(struct device *dev)
{
struct pca953x_chip *chip = dev_get_drvdata(dev);
+ mutex_lock(&chip->i2c_lock);
regcache_cache_only(chip->regmap, true);
+ mutex_unlock(&chip->i2c_lock);
if (atomic_read(&chip->wakeup_path))
device_set_wakeup_path(dev);
@@ -1186,13 +1188,17 @@ static int pca953x_resume(struct device *dev)
}
}
+ mutex_lock(&chip->i2c_lock);
regcache_cache_only(chip->regmap, false);
regcache_mark_dirty(chip->regmap);
ret = pca953x_regcache_sync(dev);
- if (ret)
+ if (ret) {
+ mutex_unlock(&chip->i2c_lock);
return ret;
+ }
ret = regcache_sync(chip->regmap);
+ mutex_unlock(&chip->i2c_lock);
if (ret) {
dev_err(dev, "Failed to restore register map: %d\n", ret);
return ret;