]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
i2c: core: ratelimit 'transfer when suspended' errors
authorWolfram Sang <wsa+renesas@sang-engineering.com>
Thu, 25 Apr 2019 14:19:47 +0000 (16:19 +0200)
committerWolfram Sang <wsa@the-dreams.de>
Fri, 3 May 2019 13:25:00 +0000 (15:25 +0200)
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>
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: stable@vger.kernel.org # v5.1+
drivers/i2c/i2c-core-base.c
include/linux/i2c.h

index 4e6300dc2c4e3d6fa43d4b618ca34d5e7c0b0811..f8e85983cb04d0276f194539ebc912dbf3b0e9a0 100644 (file)
@@ -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;
index 03755d4c9229d53eda40f631f71ffab4c939e2ff..be27062f8ed19f3e9cbbe5702a229becf9180d09 100644 (file)
@@ -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];