* [PATCH v2 1/2] i2c: core: ratelimit 'transfer when suspended' errors
2019-04-25 14:19 [PATCH v2 0/2] i2c: core: improve reporting of a suspended adapter Wolfram Sang
@ 2019-04-25 14:19 ` Wolfram Sang
2019-04-26 9:44 ` Simon Horman
2019-05-03 14:45 ` Wolfram Sang
2019-04-25 14:19 ` [PATCH v2 2/2] i2c: core: apply 'is_suspended' check for SMBus, too Wolfram Sang
1 sibling, 2 replies; 6+ messages in thread
From: Wolfram Sang @ 2019-04-25 14:19 UTC (permalink / raw)
To: linux-i2c; +Cc: Peter Rosin, linux-renesas-soc, Hans de Goede, Wolfram Sang
There are two problems with WARN_ON() here. One: It is not ratelimited.
Two: We don't see which adapter was used when trying to transfer
something when already suspended. Implement a custom ratelimit once per
adapter and use dev_WARN there. This fixes both issues. Drawback is that
we don't see if multiple drivers are trying to transfer with the same
adapter while suspended. They need to be discovered one after the other
now. This is better than a high CPU load because a really broken driver
might try to resend endlessly.
Fixes: 9ac6cb5fbb17 ("i2c: add suspended flag and accessors for i2c adapters")
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
drivers/i2c/i2c-core-base.c | 5 ++++-
include/linux/i2c.h | 3 ++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 4e6300dc2c4e..f8e85983cb04 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1867,8 +1867,11 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (WARN_ON(!msgs || num < 1))
return -EINVAL;
- if (WARN_ON(test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)))
+ if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {
+ if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))
+ dev_WARN(&adap->dev, "Transfer while suspended\n");
return -ESHUTDOWN;
+ }
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
return -EOPNOTSUPP;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 03755d4c9229..be27062f8ed1 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -694,7 +694,8 @@ struct i2c_adapter {
int retries;
struct device dev; /* the adapter device */
unsigned long locked_flags; /* owned by the I2C core */
-#define I2C_ALF_IS_SUSPENDED 0
+#define I2C_ALF_IS_SUSPENDED 0
+#define I2C_ALF_SUSPEND_REPORTED 1
int nr;
char name[48];
--
2.11.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/2] i2c: core: apply 'is_suspended' check for SMBus, too
2019-04-25 14:19 [PATCH v2 0/2] i2c: core: improve reporting of a suspended adapter Wolfram Sang
2019-04-25 14:19 ` [PATCH v2 1/2] i2c: core: ratelimit 'transfer when suspended' errors Wolfram Sang
@ 2019-04-25 14:19 ` Wolfram Sang
2019-04-26 9:44 ` Simon Horman
1 sibling, 1 reply; 6+ messages in thread
From: Wolfram Sang @ 2019-04-25 14:19 UTC (permalink / raw)
To: linux-i2c; +Cc: Peter Rosin, linux-renesas-soc, Hans de Goede, Wolfram Sang
We checked I2C calls, but not SMBus. Refactor the helper to an inline
function and use it for both, I2C and SMBus.
Fixes: 9ac6cb5fbb17 ("i2c: add suspended flag and accessors for i2c adapters")
Reported-by: Peter Rosin <peda@axentia.se>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
drivers/i2c/i2c-core-base.c | 9 ++++-----
drivers/i2c/i2c-core-smbus.c | 4 ++++
drivers/i2c/i2c-core.h | 11 +++++++++++
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index f8e85983cb04..f7ae416f1e08 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1867,11 +1867,10 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (WARN_ON(!msgs || num < 1))
return -EINVAL;
- if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {
- if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))
- dev_WARN(&adap->dev, "Transfer while suspended\n");
- return -ESHUTDOWN;
- }
+
+ ret = __i2c_check_suspended(adap);
+ if (ret)
+ return ret;
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
return -EOPNOTSUPP;
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index fdb0fb9fb9aa..788d42f2aad9 100644
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -555,6 +555,10 @@ s32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
int try;
s32 res;
+ res = __i2c_check_suspended(adapter);
+ if (res)
+ return res;
+
/* If enabled, the following two tracepoints are conditional on
* read_write and protocol.
*/
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index f9d0c417b5a5..c88cfef81343 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -54,6 +54,17 @@ static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
return ret;
}
+static inline int __i2c_check_suspended(struct i2c_adapter *adap)
+{
+ if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {
+ if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))
+ dev_WARN(&adap->dev, "Transfer while suspended\n");
+ return -ESHUTDOWN;
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_ACPI
const struct acpi_device_id *
i2c_acpi_match_device(const struct acpi_device_id *matches,
--
2.11.0
^ permalink raw reply related [flat|nested] 6+ messages in thread