Re: [RFC PATCH v6 0/4] iio: position: add Rust driver for ams AS5600

From: Muchamad Coirul Anwar

Date: Thu Oct 22 2026 - 12:10:18 EST


On Wed, 21 Oct 2026 at 23:59, Igor Korotin <igor.korotin@xxxxxxxxx> wrote:
>
> Hi Muchamad,
>
> Reviewed the lifetime/teardown contracts you asked about. read_raw() has
> a problem: it takes parent: &Device<Bound> and recovers &I2cClient<Bound>
> via TryFrom. That conversion just got removed upstream ("rust: i2c:
> remove TryFrom<&Device> implementation for &I2cClient", use-after-free,
> unrelated thread), so this won't compile anymore. More importantly, Gary
> Guo made the point that needing the conversion at all is the actual
> design issue: a class device shouldn't reach back into a generic parent
> reference during a callback -- whatever bus-specific resource it needs
> should be captured once, at registration time, and handed back via its
> own private data.
>
> Concretely, this means dropping devres and letting Data<'bound> carry a
> borrowed reference directly, which it's designed for
> (Driver::Data<'bound>: Send + 'bound):
>
> pub struct As5600Priv<'a> {
> client: &'a I2cClient<Bound>,
> #[pin]
> io_lock: Mutex<()>,
> }
>
> unsafe impl Send for As5600Priv<'_> {}
> unsafe impl Sync for As5600Priv<'_> {}
>
> unsafe impl IioDriver for As5600Priv<'_> {
> fn read_raw(&self, _chan: *const iio_chan_spec, info: IioChanInfo)
> -> Result<IioVal> {
> let client = self.client;
> ...
> }
> }
>
> In probe(), capture the client once via deref coercion (Core -> Bound)
> and split the driver struct so the registered IIO device carries the
> same 'bound lifetime:
>
> struct As5600;
>
> struct As5600Data<'bound> {
> _iio_dev: Device<As5600Priv<'bound>, Registered>,
> }
>
> impl Driver for As5600 {
> type Data<'bound> = As5600Data<'bound>;
> fn probe<'bound>(dev: &'bound I2cClient<Core<'_>>, ...) -> ... {
> let client: &'bound I2cClient<Bound> = dev;
> ...
> }
> }
>
> register() then just returns Device<T, Registered> directly instead of
> transferring it to parent devres -- that transfer is what forced T:
> 'static in the first place, which is what made storing the borrowed
> client impossible and pushed you toward TryFrom.
>
> I built this end to end against current rust-next: compiles clean, zero
> warnings, and zero changes to rust/kernel/i2c.rs. Happy to send the full
> diff if it's useful as a starting point for v7.

Hi Igor,

Thanks for working through this and building the changes. I'd be glad
to use your approach for v7, and I'd appreciate seeing the full diff you
offered.

I got the lifetime model wrong in v5 by storing an
`ARef<I2cClient<Bound>>`. I only realized that while fixing the
documentation for v6. In v6 I stopped storing that `ARef`, but ended up
relying on `TryFrom` in `read_raw()` instead.

Storing the client reference in the IIO private data rather than converting
the parent back in `read_raw()` makes sense. I'll check the lifetime and
teardown details as I prepare v7, and I'll acknowledge your contribution.

Thanks again,
Coirul


> Cheers
> Igor