[PATCH 1/2] i2c: add I2C_AQ_RUNTIME_PM adapter quirk flag
From: Hans de Goede
Date: Tue Dec 11 2018 - 13:19:17 EST
Add a new I2C_AQ_RUNTIME_PM adapter quirk flag, when this flag is set
then the i2c-core will all pm_runtime_get_sync() before calling an
adapter's master_xfer function and call pm_runtime_mark_last_busy() +
pm_runtime_put_autosuspend() after the master_xfer function.
Moving these runtime pm calls into the core for adapters which use them
is necessary for the WARN_ON(adap->is_suspended) to not trigger when
runtime-suspend is used. Another approach would be to only call
i2c_mark_adapter_suspended() from the adapter's regular suspend/resume
callbacks and not from the runtime-resume ones, but that would circumvent
the check also on system suspend when using DPM_FLAG_SMART_PREPARE or
DPM_FLAG_SMART_SUSPEND.
Note that of the 20 adapter drivers which call pm_runtime_get_sync() from
there master_xfer function, 16 call pm_runtime_put_autosuspend() when done.
i2c-nomadik.c and i2c-sh_mobile.c use pm_runtime_put_sync() and
i2c-tegra.c and i2c-rcar.c use pm_runtime_put(), so these will need to be
modified to use these new flag, or they will need another flag for their
special case.
Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
---
drivers/i2c/i2c-core-base.c | 16 ++++++++++++++--
include/linux/i2c.h | 2 ++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 5b2078a902f8..acff1e4c09d9 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1866,12 +1866,18 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (WARN_ON(!msgs || num < 1))
return -EINVAL;
- if (WARN_ON(adap->is_suspended))
- return -ESHUTDOWN;
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
return -EOPNOTSUPP;
+ if (adap->quirks && (adap->quirks->flags & I2C_AQ_RUNTIME_PM))
+ pm_runtime_get_sync(adap->dev.parent);
+
+ if (WARN_ON(adap->is_suspended)) {
+ ret = -ESHUTDOWN;
+ goto out;
+ }
+
/*
* i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets
* enabled. This is an efficient way of keeping the for-loop from
@@ -1904,6 +1910,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
trace_i2c_result(adap, num, ret);
}
+out:
+ if (adap->quirks && (adap->quirks->flags & I2C_AQ_RUNTIME_PM)) {
+ pm_runtime_mark_last_busy(adap->dev.parent);
+ pm_runtime_put_autosuspend(adap->dev.parent);
+ }
+
return ret;
}
EXPORT_SYMBOL(__i2c_transfer);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 9852038ee3a7..96b9cac6c01e 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -661,6 +661,8 @@ struct i2c_adapter_quirks {
#define I2C_AQ_NO_ZERO_LEN_READ BIT(5)
#define I2C_AQ_NO_ZERO_LEN_WRITE BIT(6)
#define I2C_AQ_NO_ZERO_LEN (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE)
+/* core must call pm_runtime_get_sync / put_autosuspend around master_xfer */
+#define I2C_AQ_RUNTIME_PM BIT(7)
/*
* i2c_adapter is the structure used to identify a physical i2c bus along
--
2.19.2
--------------5EB9D799064076BC26E44817
Content-Type: text/x-patch;
name="0002-i2c-designware-Set-is_suspended-flag-when-suspended.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename*0="0002-i2c-designware-Set-is_suspended-flag-when-suspended.pat";
filename*1="ch"