All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Gary Guo" <gary@garyguo.net>
To: "Danilo Krummrich" <dakr@kernel.org>,
	"Alistair Popple" <apopple@nvidia.com>
Cc: "nova-gpu" <nova-gpu@lists.linux.dev>,
	"M Henning" <mhenning@darkrefraction.com>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"David Airlie" <airlied@gmail.com>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Benno Lossin" <lossin@kernel.org>, "Gary Guo" <gary@garyguo.net>,
	"Eliot Courtney" <ecourtney@nvidia.com>,
	"John Hubbard" <jhubbard@nvidia.com>,
	<linux-kernel@vger.kernel.org>, <dri-devel@lists.freedesktop.org>,
	<rust-for-linux@vger.kernel.org>
Subject: Re: [PATCH v5 01/11] gpu: nova-core: Add public driver API to nova-core
Date: Mon, 31 Aug 2026 21:42:55 +0100	[thread overview]
Message-ID: <DL3F6EKL2F6Z.2DRXPQLYLE7FM@garyguo.net> (raw)
In-Reply-To: <DL3EGE1IY4FL.3X49WKCS67UT@kernel.org>

On Mon Aug 31, 2026 at 9:08 PM BST, Danilo Krummrich wrote:
> On Fri Aug 28, 2026 at 5:35 AM CEST, Alistair Popple wrote:
>> +/// API handle for the auxiliary bus child drivers to interact with nova-core.
>> +pub struct NovaCoreApi<'bound> {
>> +    #[expect(unused)]
>> +    pub(crate) gpu: Pin<&'bound Gpu<'bound>>,
>> +}
>> +
>> +impl NovaCoreApi<'_> {
>> +    /// Obtain a [`NovaCoreApi`] handle from an auxiliary device registered
>> +    /// by nova-core.
>> +    pub fn of(adev: &auxiliary::Device<Bound>) -> Result<Pin<&NovaCoreApi<'_>>> {
>> +        adev.registration_data::<CovariantForLt!(NovaCoreApi<'_>)>()
>> +    }
>> +}
>
> CovariantForLt does not hold anymore on latest drm-rust-next, as Cmdq has a
> Mutex. So, this needs ForLt now and therefore the approach that I shared in [1]
> a while ago. I applied the changes in [2] to fix it up.
>
> I think the closure access through api.with(|api| ...) is fine in most cases,
> but there are a few options if we run into cases where we consider it a bit
> inconvinient.
>
> I think it should be possible to support projections into T: 'static and
> covariant fields. The reason I differentiate them is because T: 'static is very
> convinient, but non-'static covariant types need an annoying turbofish.
>
> For T: 'static types it would turn out like this
>
> 	let spec = reg_data.api.project(|api| api.spec());
>
> such that everything that needs spec does not need to be in the closure anymore.
>
> For non-'static covariant fields we could have
>
> 	let foo = reg_data.api.project_lt::<CovariantForLt!(Foo<'_>)>(|api| api.foo());
>
> but as mentioned it unfortunately needs the turbofish. Of course we could invent
> a macro around it to get rid of the turbofish, but we'd still need to explicitly
> mention the type Foo<'_>, so it doesn't buy us a lot.
>
> This is the implementation I came up with in nova-core
>
> 	/// Projects a `'static` sub-field out of the registration data.
> 	///
> 	/// `T` is fully inferred from the closure. For projected types with a lifetime parameter,
> 	/// use [`Self::project_lt`].
> 	pub fn project<T: 'static>(
> 	    &self,
> 	    f: impl for<'b> FnOnce(Pin<&'b NovaCoreApi<'b>>) -> &'b T,
> 	) -> &'a T {
> 	    self.adev
> 	        .registration_data_field::<ForLt!(NovaCoreApi<'_>), T>(f)
> 	        .expect("TypeId was validated in NovaCoreApiHandle::of()")
> 	}
> 	
> 	/// Projects a covariant sub-field out of the registration data.
> 	///
> 	/// Supports projected types with a lifetime parameter via a
> 	/// [`CovariantForLt`](trait@CovariantForLt) encoding. Unlike [`Self::project`], `G` cannot
> 	/// be inferred and must be specified explicitly.
> 	pub fn project_lt<G: CovariantForLt + 'static>(
> 	    &self,
> 	    f: impl for<'b> FnOnce(Pin<&'b NovaCoreApi<'b>>) -> &'b G::Of<'b>,
> 	) -> &'a G::Of<'a> {
> 	    self.adev
> 	        .registration_data_project::<ForLt!(NovaCoreApi<'_>), G>(f)
> 	        .expect("TypeId was validated in NovaCoreApiHandle::of()")
> 	}
>
> and this is what we'd need in the auxiliary bus
>
> 	/// Projects a covariant sub-field out of potentially invariant registration data.
> 	///
> 	/// `F` is the [`ForLt`](trait@ForLt) encoding of the registration data type. `G` is the
> 	/// [`CovariantForLt`](trait@CovariantForLt) encoding of the projected sub-field type.
> 	///
> 	/// For projected types that are `'static`, prefer [`Self::registration_data_field`] which
> 	/// does not require a [`CovariantForLt`](trait@CovariantForLt) encoding and fully infers `T`.
> 	///
> 	/// Returns [`EINVAL`] if `F` does not match the type used by the parent driver when calling
> 	/// [`Registration::new()`]. Returns [`ENOENT`] if no registration data has been set.
> 	#[inline]
> 	pub fn registration_data_project<F, G>(
> 	    &self,
> 	    project: impl for<'a> FnOnce(Pin<&'a F::Of<'a>>) -> &'a G::Of<'a>,
> 	) -> Result<&G::Of<'_>>
> 	where
> 	    F: ForLt + 'static,
> 	    G: CovariantForLt + 'static,
> 	{
> 	    let ptr = self.registration_data_with::<F, *const ()>(|data| {
> 	        core::ptr::from_ref::<G::Of<'_>>(project(data)).cast::<()>()
> 	    })?;
> 	
> 	    // SAFETY:
> 	    // - The HRTB bound on `project` ensures the returned pointer is derived from the
> 	    //   registration data (nothing else lives for universally quantified `'a`).
> 	    // - `G: CovariantForLt` guarantees that shortening the lifetime of `G::Of` is sound.
> 	    // - The registration data is heap-allocated and outlives the device's bound state.
> 	    Ok(unsafe { &*ptr.cast::<G::Of<'_>>() })
> 	}

I think this is a bit complex, you should be able to let Rust figure out the
relation between two lifetimes.

I think if you change the signatue of `registration_data_with` slightly:

    pub fn registration_data_with<'this, F: ForLt + 'static, R>(
        &'this self,
        f: impl for<'a> FnOnce(Pin<&'this F::Of<'a>>) -> R,
                                    ^ note this is changed from 'a to 'this
    ) -> Result<R>;

then there will be an implied bound available inside the callback where 'a
outlives 'this, and thus the function callback is able to perform coercion of
any T<'a> to T<'this> provided that `T` is covariant over lifetime `'a`.

[ The coercion won't work when doing abstract `F::Of` on the bus abstraction
side, but for any user it is dealing with concrete types so the compiler sees
specific types and thus can check variance ]

Then your projection can just be

    aux.registration_data_project(|x| &x.field)

I haven't tried it out but I think it should work.

Best,
Gary


  reply	other threads:[~2026-08-31 20:43 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-28  3:35 [PATCH v5 00/11] gpu: nova: Export parameters from nova-core to nova-drm Alistair Popple
2026-08-28  3:35 ` [PATCH v5 01/11] gpu: nova-core: Add public driver API to nova-core Alistair Popple
2026-08-31 20:08   ` Danilo Krummrich
2026-08-31 20:42     ` Gary Guo [this message]
2026-09-01  7:07       ` Alistair Popple
2026-09-01  7:14         ` Danilo Krummrich
2026-09-01  9:13           ` Alistair Popple
2026-09-01  9:21             ` Danilo Krummrich
2026-09-01 10:27       ` Danilo Krummrich
2026-09-01 11:35         ` Gary Guo
2026-09-01  3:53     ` Alistair Popple
2026-09-02  6:57     ` Alistair Popple
2026-09-02 19:30       ` Danilo Krummrich
2026-08-28  3:35 ` [PATCH v5 02/11] drm: nova: Add DRM registration data Alistair Popple
2026-08-28  3:35 ` [PATCH v5 03/11] drm: nova: Add GPU architecture enum to nova-drm UAPI Alistair Popple
2026-08-28  3:35 ` [PATCH v5 04/11] rust: uaccess: add UserSliceWriter::write_truncated() Alistair Popple
2026-08-28  3:35 ` [PATCH v5 05/11] drm: nova: Add an info ioctl Alistair Popple
2026-08-31  4:58   ` Alistair Popple
2026-08-31 14:23   ` Danilo Krummrich
2026-09-01  3:47     ` Alistair Popple
2026-09-01  4:50       ` Dave Airlie
2026-09-01  5:09         ` Alistair Popple
2026-09-01  7:29           ` Danilo Krummrich
2026-09-02  5:21             ` Alistair Popple
2026-09-02  7:05               ` Alistair Popple
2026-09-02 19:26                 ` Danilo Krummrich
2026-09-02 19:38                   ` Dave Airlie
2026-09-02 19:42                     ` Danilo Krummrich
2026-09-01  4:53   ` Dave Airlie
2026-09-01  5:24     ` Alistair Popple
2026-09-01 10:38   ` Danilo Krummrich
2026-09-01 17:01     ` Danilo Krummrich
2026-09-02  2:38       ` Alistair Popple
2026-09-02  9:40         ` Danilo Krummrich
2026-09-03  1:12           ` Alistair Popple
2026-09-03 10:42             ` Danilo Krummrich
2026-09-04  7:49               ` Alistair Popple
2026-09-04  9:34                 ` Danilo Krummrich
2026-09-08  6:47                   ` Alistair Popple
2026-09-04 11:13               ` Gary Guo
2026-09-04 12:08                 ` Danilo Krummrich
2026-09-08  7:11                   ` Alistair Popple
2026-09-08  7:59                     ` Dave Airlie
2026-09-08 14:48               ` M Henning
2026-09-08 16:57                 ` Danilo Krummrich
2026-09-08 21:20                   ` M Henning
2026-08-28  3:35 ` [PATCH v5 06/11] drm: nova: Add usable VRAM size to GPU info Alistair Popple
2026-08-28  3:35 ` [PATCH v5 07/11] drm: nova: Use nova-core to read VRAM_BAR_SIZE parameter Alistair Popple
2026-08-28  3:35 ` [PATCH v5 08/11] drm: nova: Expose a render node Alistair Popple
2026-08-28  3:35 ` [PATCH v5 09/11] drm: nova: Report GPU name in GPU info Alistair Popple
2026-08-31 14:33   ` Danilo Krummrich
2026-09-01  3:09     ` Alistair Popple
2026-08-28  3:35 ` [PATCH v5 10/11] drm: nova: Report GPU short " Alistair Popple
2026-08-31 14:41   ` Danilo Krummrich
2026-09-01  3:10     ` Alistair Popple
2026-08-28  3:35 ` [PATCH v5 11/11] drm: nova: Report GPU GID " Alistair Popple
2026-08-28  6:04 ` [PATCH v5 00/11] gpu: nova: Export parameters from nova-core to nova-drm Alistair Popple

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DL3F6EKL2F6Z.2DRXPQLYLE7FM@garyguo.net \
    --to=gary@garyguo.net \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=apopple@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=ecourtney@nvidia.com \
    --cc=jhubbard@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=mhenning@darkrefraction.com \
    --cc=nova-gpu@lists.linux.dev \
    --cc=rust-for-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.