Re: [PATCH v2 1/2] rust: introduce abstractions for fwctlg

Jason Gunthorpe
2026-01-28T13:20:43Z

On Wed, Jan 28, 2026 at 02:21:38AM +0100, Danilo Krummrich wrote:
> On Wed Jan 28, 2026 at 1:04 AM CET, Jason Gunthorpe wrote:
> > On Tue, Jan 27, 2026 at 09:07:37PM +0100, Danilo Krummrich wrote:
> >> On Tue Jan 27, 2026 at 8:57 PM CET, Zhi Wang wrote:
> >> > The fwctl_alloc_device() helper allocates a raw struct fwctl_device
> >> > without private driver data here. The Rust driver object should be
> >> > already allocated and initialized separately before reaching this
> >> > point.
> >> >
> >> > We rely on the standard dev->parent chain to access the rust driver
> >> > object from the fwctl callbacks.
> >>
> >> (I will go for a thorough review soon, but for now a quick drive-by comment.)
> >>
> >> IIUC, you are saying that the user is supposed to use the private data of the
> >> parent device in fwctl callbacks. Let's not make this a design choice please.
> >> Instead, allow the user pass in separate private data for the fwctl device as
> >> well.
> >>
> >> This serves the purpose of clear ownership and lifetime of the data. E.g. the
> >> fwctl device does not necessarily exist as long as the parent device is bound.
> >>
> >> It is a good thing if driver authors are forced to take a decision about which
> >> object owns the data and what's the scope of the data.
>
> I think we were talking about different things. :)

Well, I've always been talking about this :)

> In this case Registration::new() returns an initializer, but also allocates the
> C struct fwctl_device within the initializer.

In a normal C implementation this would allocate both the core and
driver struct using one memory and a container_of() relationship.

> AFAICS, _fwctl_alloc_device() already initializes the structure properly, so it
> seems there is nothing to be done.

It does the first part of a three step sequence

1) Allocate memory and initialize core code
2) Steup driver related data
3) "register" to make the device live and begin concurrent access

I don't think 1 and 3 can be in the same function. The driver must have
the opportunity to do its #2 step in this sequence.

> Though, sometimes there are cases where we have to defer some initialization.
> This is where we usually use separate types or type states. Let's assume
> something in the device only ever gets initialized after registration for some
> reason. In this case you could have a fwctl::Device<Unregistred> and a
> fwctl::Device<Registered> and correspondingly treat the inner data as partially
> uninitialized (which requires unsafe code).

Maybe this is what is needed here then.

> Either way, I think it would be cleaner if fwctl::Device has a constructor
>
> impl Device<T> {
> fn new(
> parent: &Device<Bound>,
> data: impl PinInit<T, Error>
> ) -> Result<ARef<Self>>;
> }
>
> where T is the driver's private data for the struct fwctl_device.
>
> And Registration::new() can take a &fwctl::Device<T> and the parent
> &Device<Bound> of course. This would also be in line with what we do in other
> class device abstractions.

If it goes like this is there some way rust can retain the
container_of layout and avoid a second memory allocation?

Jason