mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
i2c: atr: serialize attach/detach against bus transfers
The attach_addr() and detach_addr() callbacks may need to reconfigure the remote side of the bus. Maxim GMSL deserializers, for example, disable all links but one to reach a serializer at its default address, since all serializers power up at the same address. Transfers on other channels of the same ATR can run concurrently with these callbacks and fail with -EIO while the links are disabled. Take the ATR bus lock around both callbacks, before alias_pairs_lock. i2c_atr_replace_mapping_by_addr() already calls them under this lock, so ATR drivers see no new constraint. Suggested-by: Quentin Freimanis <quentin@q-lab.dev> Signed-off-by: Dumitru Ceclan <dumitru.ceclan@analog.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
This commit is contained in:
parent
7398f90718
commit
424e37817b
|
|
@ -540,6 +540,12 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
|
|||
struct i2c_atr_alias_pair *c2a;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* attach_addr() may reconfigure the remote side of the bus, keep
|
||||
* transfers on other channels out until it is done.
|
||||
*/
|
||||
mutex_lock(&atr->lock);
|
||||
|
||||
mutex_lock(&chan->alias_pairs_lock);
|
||||
|
||||
c2a = i2c_atr_create_mapping_by_addr(chan, addr);
|
||||
|
|
@ -557,6 +563,8 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
|
|||
|
||||
out_unlock:
|
||||
mutex_unlock(&chan->alias_pairs_lock);
|
||||
mutex_unlock(&atr->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -567,6 +575,8 @@ static void i2c_atr_detach_addr(struct i2c_adapter *adapter,
|
|||
struct i2c_atr *atr = chan->atr;
|
||||
struct i2c_atr_alias_pair *c2a;
|
||||
|
||||
mutex_lock(&atr->lock);
|
||||
|
||||
atr->ops->detach_addr(atr, chan->chan_id, addr);
|
||||
|
||||
mutex_lock(&chan->alias_pairs_lock);
|
||||
|
|
@ -574,6 +584,7 @@ static void i2c_atr_detach_addr(struct i2c_adapter *adapter,
|
|||
c2a = i2c_atr_find_mapping_by_addr(chan, addr);
|
||||
if (!c2a) {
|
||||
mutex_unlock(&chan->alias_pairs_lock);
|
||||
mutex_unlock(&atr->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -586,6 +597,7 @@ static void i2c_atr_detach_addr(struct i2c_adapter *adapter,
|
|||
i2c_atr_destroy_c2a(&c2a);
|
||||
|
||||
mutex_unlock(&chan->alias_pairs_lock);
|
||||
mutex_unlock(&atr->lock);
|
||||
}
|
||||
|
||||
static int i2c_atr_bus_notifier_call(struct notifier_block *nb,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user