diff --git a/drivers/i2c/i2c-atr.c b/drivers/i2c/i2c-atr.c index e6d2af659d81..f7d1d6e41cdc 100644 --- a/drivers/i2c/i2c-atr.c +++ b/drivers/i2c/i2c-atr.c @@ -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,