[PATCH 01/11] i2c: add helpers for locking the I2C segment

From: Peter Rosin
Date: Fri Jun 15 2018 - 06:19:01 EST


This is what almost all drivers want to do. By only advertising
i2c_lock_adapter, they are tricked into locking the root adapter
which is too big of a hammer in most cases.

While at it, convert all open-coded locking of the I2C segment.

Signed-off-by: Peter Rosin <peda@xxxxxxxxxx>
---
drivers/i2c/i2c-core-base.c | 6 +++---
drivers/i2c/i2c-core-smbus.c | 4 ++--
include/linux/i2c.h | 18 ++++++++++++++++++
3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 1ba40bb2b966..3eb09dc20573 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1932,16 +1932,16 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
#endif

if (in_atomic() || irqs_disabled()) {
- ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
+ ret = i2c_trylock_segment(adap);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
} else {
- i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
+ i2c_lock_segment(adap);
}

ret = __i2c_transfer(adap, msgs, num);
- i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
+ i2c_unlock_segment(adap);

return ret;
} else {
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index b5aec33002c3..8a820fdef3e0 100644
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -537,7 +537,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;

if (adapter->algo->smbus_xfer) {
- i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
+ i2c_lock_segment(adapter);

/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
@@ -551,7 +551,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
orig_jiffies + adapter->timeout))
break;
}
- i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
+ i2c_unlock_segment(adapter);

if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
goto trace;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 44ad14e016b5..c9080d49e988 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -768,6 +768,24 @@ i2c_unlock_adapter(struct i2c_adapter *adapter)
i2c_unlock_bus(adapter, I2C_LOCK_ROOT_ADAPTER);
}

+static inline void
+i2c_lock_segment(struct i2c_adapter *adapter)
+{
+ i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
+}
+
+static inline int
+i2c_trylock_segment(struct i2c_adapter *adapter)
+{
+ return i2c_trylock_bus(adapter, I2C_LOCK_SEGMENT);
+}
+
+static inline void
+i2c_unlock_segment(struct i2c_adapter *adapter)
+{
+ i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
+}
+
/*flags for the client struct: */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
--
2.11.0