Re: Two separate i2c transfers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Peter,

W dniu 15.05.2020 o 10:02, Peter Rosin pisze:
> 
> 
> On 2020-05-15 09:04, Adamski, Krzysztof (Nokia - PL/Wrocław) wrote:
>> Hi Wolfram, Peter,
>>
>> Thank you for the quick response.
>>
>> W dniu 14.05.2020 o 16:50, Wolfram Sang pisze:
>>> Hi Krzysztof,
>>>
>>> On Thu, May 14, 2020 at 02:41:17PM +0200, Adamski, Krzysztof (Nokia - PL/Wrocław) wrote:
>>>
>>> Adding Peter as the mux maintainer to CC.
>>>
>>>> I have a problem that I think cannot be currently easily addressed by I2C framework in the kernel and I'm seeking for an
>>>> advice on how to approach this. I have an I2C device that can be accessed from two I2C masters connected to I2C bus
>>>> master selector channels. Both masters must do such a sequence before performing long operation:
>>>
>>> I need a diagram of that setup. What is the BMS? A chip? Some software?
>>> Can you draw a graph and give names of chips etc...?
>>>
>>> And, of course, why on earth do you need to access the same chip from
>>> two masters within one Linux? :) (That's how I understood it)
>>>
> 
> *snip* useful layout.
> 
>> I was thinking that maybe a lock like this could be expressed by i2c_lock_bus with some special flag that would make
>> sure no deselect is called in i2c_mux_master_xfer() (and would be ignored if our parent is not an arbiter)? We already
>> have the I2C_MUX_ARBITRATOR flag and the i2c_mux_core does have an arbitrator bool so it is just a matter of allowing to
>> do this kind of deeper lock on the bus.
> 
> Yes, that definitely makes it clearer. So, what you need is something
> more complex than an I2C xfer between select/deselect. Your proposal
> to add a flag to not do the deselect should probably have a matching
> flag to not do the select on the following xfer. Otherwise that second
> xfer is likely to do useless work. This should probably also be two
> independent flags, so that you can add intermediate xfers that neither
> select nor deselect. But you also need an explicit deselect mechanism
> for use if there is a problem half way through...
> 
> But, I think all that exposes the too much to the users, and while it
> is certainly possible (most things are), I not a huge fan of it.
> Maintainers of other subsystems will not know the rules, and drivers
> are, over time, bound to start using these facilities in half-baked
> ways.
> 
> I would rather have some generic I2C mechanism to request more than
> a single xfer as a unit, such that the muxes/arbs/gates can then lock
> the mux/arb/gate, do the select, feed the unit to the parent adapter
> and finally deselect and unlock the mux/arb/gate. With the locking
> and selecting centralized instead of spread out to all users. This
> helps avoid bugs where things are not cleaned up on error paths etc.
> 

Hmm.. but isn't such a "unit" expressed right now by using i2c_lock_bus()? If you want to do more transfers and do not
want to be disturbed by anyone on local system, you do:

i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
 __i2c_transfer(client->adapter, ...);
 some_logic
 __ice_transfer(client->adapter, ...);
i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);

right? So my idea would be to extend it to "outside of local system" if we have an arbiter as a parent. To not change
existing semantics, that might require additional flag (so such a "deeper lock" would be opt-in):

i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER | I2C_LOCK_ARBITRATOR);
 __i2c_transfer(client->adapter, ...)
 some_logic
 __ice_transfer(client->adapter, ...)
i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER | I2C_LOCK_ARBITRATOR);


The I2C_LOCK_ARBITER flag would only be relevant for i2c_mux_lock_bus() that could do:
if (muxc->arbitrator && flags & I2C_LOCK_ARBITRATOR) {
    priv->muxc->select(muxc, priv->chan_id);
    priv->muxc->arbitrator_selected = true;
}

and unlock could do the opposite:
if (muxc->arbitrator && flags & I2C_LOCK_ARBITRATOR) {
    priv->muxc->select(muxc, priv->chan_id);
    priv->muxc->arbitrator_selected = true;
}

Now we would also need to change the xfer functions in i2c-mux.c to check for muxc->arbitrator_selected - if it is set,
it would skip doing both select and deselect as this "flag" would mean that selecting/deselecting is done on lock/unlock
and not on transfer level. Of course we could also skip the check for muxc->arbitrator if you think such a lock could
make sense for other types of muxes as well..

Would that really be confusing / un-intutive ?

Best regards,



[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux