aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-core.c
diff options
context:
space:
mode:
authorPeter Rosin <peda@axentia.se>2016-05-04 16:15:27 -0400
committerWolfram Sang <wsa@the-dreams.de>2016-05-04 16:28:31 -0400
commit8320f495cf441d593f7cd4f30e6b63455be71a2c (patch)
tree6c82e3477b5de9200ef237d7a3ac807cf9adb52a /drivers/i2c/i2c-core.c
parent8a350183010a5557287a10c2a13b1a4cbaa7b130 (diff)
i2c: allow adapter drivers to override the adapter locking
Add i2c_lock_bus() and i2c_unlock_bus(), which call the new lock_bus and unlock_bus ops in the adapter. These funcs/ops take an additional flags argument that indicates for what purpose the adapter is locked. There are two flags, I2C_LOCK_ROOT_ADAPTER and I2C_LOCK_SEGMENT, but they are both implemented the same. For now. Locking the root adapter means that the whole bus is locked, locking the segment means that only the current bus segment is locked (i.e. i2c traffic on the parent side of a mux is still allowed even if the child side of the mux is locked). Also support a trylock_bus op (but no function to call it, as it is not expected to be needed outside of the i2c core). Implement i2c_lock_adapter/i2c_unlock_adapter in terms of the new locking scheme (i.e. lock with the I2C_LOCK_ROOT_ADAPTER flag). Locking the root adapter and locking the segment is the same thing for all root adapters (e.g. in the normal case of a simple topology with no i2c muxes). The two locking variants are also the same for traditional muxes (aka parent-locked muxes). These muxes traverse the tree, locking each level as they go until they reach the root. This patch is preparatory for a later patch in the series introducing mux-locked muxes, which behave differently depending on the requested locking. Since all current users are using i2c_lock_adapter, which is a wrapper for I2C_LOCK_ROOT_ADAPTER, we only need to annotate the calls that will not need to lock the root adapter for mux-locked muxes. I.e. the instances that needs to use I2C_LOCK_SEGMENT instead of i2c_lock_adapter/I2C_LOCK_ROOT_ADAPTER. Those instances are in the i2c_transfer and i2c_smbus_xfer functions, so that mux-locked muxes can single out normal i2c accesses to its slave side and adjust the locking for those accesses. Signed-off-by: Peter Rosin <peda@axentia.se> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r--drivers/i2c/i2c-core.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 4979728f7fb2..7ef5bd085476 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -954,10 +954,13 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr)
954} 954}
955 955
956/** 956/**
957 * i2c_lock_adapter - Get exclusive access to an I2C bus segment 957 * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment
958 * @adapter: Target I2C bus segment 958 * @adapter: Target I2C bus segment
959 * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
960 * locks only this branch in the adapter tree
959 */ 961 */
960void i2c_lock_adapter(struct i2c_adapter *adapter) 962static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
963 unsigned int flags)
961{ 964{
962 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); 965 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
963 966
@@ -966,27 +969,32 @@ void i2c_lock_adapter(struct i2c_adapter *adapter)
966 else 969 else
967 rt_mutex_lock(&adapter->bus_lock); 970 rt_mutex_lock(&adapter->bus_lock);
968} 971}
969EXPORT_SYMBOL_GPL(i2c_lock_adapter);
970 972
971/** 973/**
972 * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment 974 * i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment
973 * @adapter: Target I2C bus segment 975 * @adapter: Target I2C bus segment
976 * @flags: I2C_LOCK_ROOT_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT
977 * trylocks only this branch in the adapter tree
974 */ 978 */
975static int i2c_trylock_adapter(struct i2c_adapter *adapter) 979static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter,
980 unsigned int flags)
976{ 981{
977 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); 982 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
978 983
979 if (parent) 984 if (parent)
980 return i2c_trylock_adapter(parent); 985 return parent->trylock_bus(parent, flags);
981 else 986 else
982 return rt_mutex_trylock(&adapter->bus_lock); 987 return rt_mutex_trylock(&adapter->bus_lock);
983} 988}
984 989
985/** 990/**
986 * i2c_unlock_adapter - Release exclusive access to an I2C bus segment 991 * i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment
987 * @adapter: Target I2C bus segment 992 * @adapter: Target I2C bus segment
993 * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT
994 * unlocks only this branch in the adapter tree
988 */ 995 */
989void i2c_unlock_adapter(struct i2c_adapter *adapter) 996static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
997 unsigned int flags)
990{ 998{
991 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); 999 struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
992 1000
@@ -995,7 +1003,6 @@ void i2c_unlock_adapter(struct i2c_adapter *adapter)
995 else 1003 else
996 rt_mutex_unlock(&adapter->bus_lock); 1004 rt_mutex_unlock(&adapter->bus_lock);
997} 1005}
998EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
999 1006
1000static void i2c_dev_set_name(struct i2c_adapter *adap, 1007static void i2c_dev_set_name(struct i2c_adapter *adap,
1001 struct i2c_client *client) 1008 struct i2c_client *client)
@@ -1541,6 +1548,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
1541 return -EINVAL; 1548 return -EINVAL;
1542 } 1549 }
1543 1550
1551 if (!adap->lock_bus) {
1552 adap->lock_bus = i2c_adapter_lock_bus;
1553 adap->trylock_bus = i2c_adapter_trylock_bus;
1554 adap->unlock_bus = i2c_adapter_unlock_bus;
1555 }
1556
1544 rt_mutex_init(&adap->bus_lock); 1557 rt_mutex_init(&adap->bus_lock);
1545 mutex_init(&adap->userspace_clients_lock); 1558 mutex_init(&adap->userspace_clients_lock);
1546 INIT_LIST_HEAD(&adap->userspace_clients); 1559 INIT_LIST_HEAD(&adap->userspace_clients);
@@ -2310,16 +2323,16 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
2310#endif 2323#endif
2311 2324
2312 if (in_atomic() || irqs_disabled()) { 2325 if (in_atomic() || irqs_disabled()) {
2313 ret = i2c_trylock_adapter(adap); 2326 ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT);
2314 if (!ret) 2327 if (!ret)
2315 /* I2C activity is ongoing. */ 2328 /* I2C activity is ongoing. */
2316 return -EAGAIN; 2329 return -EAGAIN;
2317 } else { 2330 } else {
2318 i2c_lock_adapter(adap); 2331 i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
2319 } 2332 }
2320 2333
2321 ret = __i2c_transfer(adap, msgs, num); 2334 ret = __i2c_transfer(adap, msgs, num);
2322 i2c_unlock_adapter(adap); 2335 i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
2323 2336
2324 return ret; 2337 return ret;
2325 } else { 2338 } else {
@@ -3094,7 +3107,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
3094 flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB; 3107 flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
3095 3108
3096 if (adapter->algo->smbus_xfer) { 3109 if (adapter->algo->smbus_xfer) {
3097 i2c_lock_adapter(adapter); 3110 i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
3098 3111
3099 /* Retry automatically on arbitration loss */ 3112 /* Retry automatically on arbitration loss */
3100 orig_jiffies = jiffies; 3113 orig_jiffies = jiffies;
@@ -3108,7 +3121,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
3108 orig_jiffies + adapter->timeout)) 3121 orig_jiffies + adapter->timeout))
3109 break; 3122 break;
3110 } 3123 }
3111 i2c_unlock_adapter(adapter); 3124 i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
3112 3125
3113 if (res != -EOPNOTSUPP || !adapter->algo->master_xfer) 3126 if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
3114 goto trace; 3127 goto trace;