Skip to content

Commit

Permalink
i2c: core: use I2C locking behaviour also for SMBUS
Browse files Browse the repository at this point in the history
If I2C transfers are executed in atomic contexts, trylock is used
instead of lock. This behaviour was missing for SMBUS, although a lot of
transfers are of SMBUS type, either emulated or direct. So, factor out
the locking routine into a helper and use it for I2C and SMBUS.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
  • Loading branch information
Wolfram Sang authored and Wolfram Sang committed Apr 16, 2019
1 parent bae1d3a commit 83c4221
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 9 deletions.
11 changes: 3 additions & 8 deletions drivers/i2c/i2c-core-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1946,14 +1946,9 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
* one (discarding status on the second message) or errno
* (discarding status on the first one).
*/
if (i2c_in_atomic_xfer_mode()) {
ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
} else {
i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
}
ret = __i2c_lock_bus_helper(adap);
if (ret)
return ret;

ret = __i2c_transfer(adap, msgs, num);
i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
Expand Down
7 changes: 6 additions & 1 deletion drivers/i2c/i2c-core-smbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <linux/i2c-smbus.h>
#include <linux/slab.h>

#include "i2c-core.h"

#define CREATE_TRACE_POINTS
#include <trace/events/smbus.h>

Expand Down Expand Up @@ -530,7 +532,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
{
s32 res;

i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
res = __i2c_lock_bus_helper(adapter);
if (res)
return res;

res = __i2c_smbus_xfer(adapter, addr, flags, read_write,
command, protocol, data);
i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
Expand Down
12 changes: 12 additions & 0 deletions drivers/i2c/i2c-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ static inline bool i2c_in_atomic_xfer_mode(void)
return system_state > SYSTEM_RUNNING && irqs_disabled();
}

static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
{
int ret = 0;

if (i2c_in_atomic_xfer_mode())
ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT) ? 0 : -EAGAIN;
else
i2c_lock_bus(adap, I2C_LOCK_SEGMENT);

return ret;
}

#ifdef CONFIG_ACPI
const struct acpi_device_id *
i2c_acpi_match_device(const struct acpi_device_id *matches,
Expand Down

0 comments on commit 83c4221

Please sign in to comment.