diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 02:48:12 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 02:48:12 +0200 |
commit | 78975f23cba0cd195db01cdbd6eb48138a655890 (patch) | |
tree | 0e808c0cfe220bd8fb00d66985d71655345904cb /drivers/i2c/i2c-core.c | |
parent | Merge tag 'md/4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md (diff) | |
parent | i2c: rcar: add DMA support (diff) | |
download | linux-78975f23cba0cd195db01cdbd6eb48138a655890.tar.xz linux-78975f23cba0cd195db01cdbd6eb48138a655890.zip |
Merge branch 'i2c/for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
- Peter Rosin did some major rework on the locking of i2c muxes by
seperating parent-locked muxes and mux-locked muxes.
This avoids deadlocks/workarounds when the mux itself needs i2c
commands for muxing. And as a side-effect, other workarounds in the
media layer could be eliminated. Also, Peter stepped up as the i2c
mux maintainer and will keep an eye on these changes.
- major updates to the octeon driver
- add a helper to the core to generate the address+rw_bit octal and
make drivers use it
- quite a bunch of driver updates
* 'i2c/for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (84 commits)
i2c: rcar: add DMA support
i2c: st: Implement bus clear
i2c: only check scl functions when using generic recovery
i2c: algo-bit: declare i2c_bit_quirk_no_clk_stretch as static
i2c: tegra: disable clock before returning error
[media] rtl2832: regmap is aware of lockdep, drop local locking hack
[media] rtl2832_sdr: get rid of empty regmap wrappers
[media] rtl2832: change the i2c gate to be mux-locked
[media] si2168: change the i2c gate to be mux-locked
iio: imu: inv_mpu6050: change the i2c gate to be mux-locked
i2c: mux: document i2c muxes and elaborate on parent-/mux-locked muxes
i2c: mux: relax locking of the top i2c adapter during mux-locked muxing
i2c: muxes always lock the parent adapter
i2c: allow adapter drivers to override the adapter locking
i2c: uniphier: add "\n" at the end of error log
i2c: mv64xxx: remove CONFIG_HAVE_CLK conditionals
i2c: mv64xxx: use clk_{prepare_enable,disable_unprepare}
i2c: mv64xxx: handle probe deferral for the clock
i2c: mv64xxx: enable the driver on ARCH_MVEBU
i2c: octeon: Add workaround for broken irqs on CN3860
...
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r-- | drivers/i2c/i2c-core.c | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e584d88ee337..af11b658984d 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -954,48 +954,40 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) } /** - * i2c_lock_adapter - Get exclusive access to an I2C bus segment + * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment * @adapter: Target I2C bus segment + * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT + * locks only this branch in the adapter tree */ -void i2c_lock_adapter(struct i2c_adapter *adapter) +static void i2c_adapter_lock_bus(struct i2c_adapter *adapter, + unsigned int flags) { - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - - if (parent) - i2c_lock_adapter(parent); - else - rt_mutex_lock(&adapter->bus_lock); + rt_mutex_lock(&adapter->bus_lock); } -EXPORT_SYMBOL_GPL(i2c_lock_adapter); /** - * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment + * i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment * @adapter: Target I2C bus segment + * @flags: I2C_LOCK_ROOT_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT + * trylocks only this branch in the adapter tree */ -static int i2c_trylock_adapter(struct i2c_adapter *adapter) +static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter, + unsigned int flags) { - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - - if (parent) - return i2c_trylock_adapter(parent); - else - return rt_mutex_trylock(&adapter->bus_lock); + return rt_mutex_trylock(&adapter->bus_lock); } /** - * i2c_unlock_adapter - Release exclusive access to an I2C bus segment + * i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment * @adapter: Target I2C bus segment + * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT + * unlocks only this branch in the adapter tree */ -void i2c_unlock_adapter(struct i2c_adapter *adapter) +static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter, + unsigned int flags) { - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - - if (parent) - i2c_unlock_adapter(parent); - else - rt_mutex_unlock(&adapter->bus_lock); + rt_mutex_unlock(&adapter->bus_lock); } -EXPORT_SYMBOL_GPL(i2c_unlock_adapter); static void i2c_dev_set_name(struct i2c_adapter *adap, struct i2c_client *client) @@ -1541,7 +1533,14 @@ static int i2c_register_adapter(struct i2c_adapter *adap) return -EINVAL; } + if (!adap->lock_bus) { + adap->lock_bus = i2c_adapter_lock_bus; + adap->trylock_bus = i2c_adapter_trylock_bus; + adap->unlock_bus = i2c_adapter_unlock_bus; + } + rt_mutex_init(&adap->bus_lock); + rt_mutex_init(&adap->mux_lock); mutex_init(&adap->userspace_clients_lock); INIT_LIST_HEAD(&adap->userspace_clients); @@ -1559,6 +1558,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); pm_runtime_no_callbacks(&adap->dev); + pm_suspend_ignore_children(&adap->dev, true); pm_runtime_enable(&adap->dev); #ifdef CONFIG_I2C_COMPAT @@ -1594,10 +1594,12 @@ static int i2c_register_adapter(struct i2c_adapter *adap) bri->get_scl = get_scl_gpio_value; bri->set_scl = set_scl_gpio_value; - } else if (!bri->set_scl || !bri->get_scl) { + } else if (bri->recover_bus == i2c_generic_scl_recovery) { /* Generic SCL recovery */ - dev_err(&adap->dev, "No {get|set}_gpio() found, not using recovery\n"); - adap->bus_recovery_info = NULL; + if (!bri->set_scl || !bri->get_scl) { + dev_err(&adap->dev, "No {get|set}_scl() found, not using recovery\n"); + adap->bus_recovery_info = NULL; + } } } @@ -2309,16 +2311,16 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) #endif if (in_atomic() || irqs_disabled()) { - ret = i2c_trylock_adapter(adap); + ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT); if (!ret) /* I2C activity is ongoing. */ return -EAGAIN; } else { - i2c_lock_adapter(adap); + i2c_lock_bus(adap, I2C_LOCK_SEGMENT); } ret = __i2c_transfer(adap, msgs, num); - i2c_unlock_adapter(adap); + i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); return ret; } else { @@ -2646,7 +2648,7 @@ static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) { /* The address will be sent first */ - u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD); + u8 addr = i2c_8bit_addr_from_msg(msg); pec = i2c_smbus_pec(pec, &addr, 1); /* The data buffer follows */ @@ -3093,7 +3095,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_adapter(adapter); + i2c_lock_bus(adapter, I2C_LOCK_SEGMENT); /* Retry automatically on arbitration loss */ orig_jiffies = jiffies; @@ -3107,7 +3109,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, orig_jiffies + adapter->timeout)) break; } - i2c_unlock_adapter(adapter); + i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT); if (res != -EOPNOTSUPP || !adapter->algo->master_xfer) goto trace; |