From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 967742C11D2 for ; Fri, 29 Aug 2025 22:41:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507306; cv=none; b=Jk7GoXlwAS9jPr7JRXsXI5y/wUYLQno9vydw/u3SjhjLHj+KQMsB1eipAQVS3wxwAU5p6osTDQH+0zTkekIK7PI96lo1A/KwAZ82SgI2GTCdhV7dYMwQzZsjnglavk8oN5sEpyy6eoPOaTv+NDs6g9hxeY1+NF/NZ2azg5RI8aw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507306; c=relaxed/simple; bh=93D01/9MGYeQxAYQMPpZbkr8XEKJoXkgMJrGZe51BZ4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Izrp8kUcVOw8AoVXmUQ1rHLjmi5K5d2AmkB5RHrFeZWBhVxgmutd6dCzDy+ac87cuW8fAHuJC5/FibYwJV/dBPW1DpO8P/tupNvwPCj25jWy1a+oiSsWgaOWD1igpm5EgqSL5vU5+rlo2ksYj5f8gbpHe+yujRELJeG/BXSjgUg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=gFdcZK6H; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="gFdcZK6H" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507303; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=s8i4OdfWtC0nfVa/WzC9Lo9f419vHR68HZ0XadmVT3A=; b=gFdcZK6HNE5beO8ar8fj8jE5Jqi1MdTGXq3xNro/aFfZW9fl7CKzVptZ0uddrwx64kK5BB 4r6lD6BIxXWeKCSqnQ6hmRJu9cXbxELok5NVD1NPXnevehInHe+xGMFhtiUzbWqQBkQ2Kc G8ZQ4ZQrRl0UdZG0NPognE3kasefjp8= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-649-__9KvojgM4m79NeVznTVwA-1; Fri, 29 Aug 2025 18:41:38 -0400 X-MC-Unique: __9KvojgM4m79NeVznTVwA-1 X-Mimecast-MFC-AGG-ID: __9KvojgM4m79NeVznTVwA_1756507296 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 88AEE19560B5; Fri, 29 Aug 2025 22:41:35 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B89961800447; Fri, 29 Aug 2025 22:41:30 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Asahi Lina , nouveau@lists.freedesktop.org (open list:DRM DRIVER FOR NVIDIA GPUS [RUST]) Subject: [PATCH v3 01/14] rust: drm: gem: Simplify use of generics Date: Fri, 29 Aug 2025 18:35:16 -0400 Message-ID: <20250829224116.477990-2-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Now that my rust skills have been honed, I noticed that there's a lot of generics in our gem bindings that don't actually need to be here. Currently the hierarchy of traits in our gem bindings looks like this: * Drivers implement: * BaseDriverObject (has the callbacks) * DriverObject (has the drm::Driver type) * Crate implements: * IntoGEMObject for Object where T: DriverObject Handles conversion to/from raw object pointers * BaseObject for T where T: IntoGEMObject Provides methods common to all gem interfaces Also of note, this leaves us with two different drm::Driver associated types: * DriverObject::Driver * IntoGEMObject::Driver I'm not entirely sure of the original intent here unfortunately (if anyone is, please let me know!), but my guess is that the idea would be that some objects can implement IntoGEMObject using a different ::Driver than DriverObject - presumably to enable the usage of gem objects from different drivers. A reasonable usecase of course. However - if I'm not mistaken, I don't think that this is actually how things would go in practice. Driver implementations are of course implemented by their associated drivers, and generally drivers are not linked to each-other when building the kernel. Which is to say that even in a situation where we would theoretically deal with gem objects from another driver, we still wouldn't have access to its drm::driver::Driver implementation. It's more likely we would simply want a variant of gem objects in such a situation that have no association with a drm::driver::Driver type. Taking that into consideration, we can assume the following: * Anything that implements BaseDriverObject will implement DriverObject In other words, all BaseDriverObjects indirectly have an associated ::Driver type - so the two traits can be combined into one with no generics. * Not everything that implements IntoGEMObject will have an associated ::Driver, and that's OK. And with this, we now can do quite a bit of cleanup with the use of generics here. As such, this commit: * Removes the generics on BaseDriverObject * Moves DriverObject::Driver into BaseDriverObject * Removes DriverObject * Removes IntoGEMObject::Driver * Add AllocImpl::Driver, which we can use as a binding to figure out the correct File type for BaseObject Leaving us with a simpler trait hierarchy that now looks like this: * Drivers implement: BaseDriverObject * Crate implements: * IntoGEMObject for Object where T: DriverObject * BaseObject for T where T: IntoGEMObject Which makes the code a lot easier to understand and build on :). Signed-off-by: Lyude Paul Reviewed-by: Daniel Almeida --- V2: * Don't refer to Object in callbacks, as this would result in drivers getting the wrong gem object type for shmem gem objects once we add support for those. Instead, we'll just add a type alias to clean this part up. V3: * Fix nova compilation * Also, add an associated driver type to AllocImpl - as we still need the current driver accessible from BaseObject so that we can use the driver's various associated types, like File V4: * Add missing Object =3D Self constraint to type bounds for create_handle, lookup_handle. I forgot that if drivers can have private gem objects with a different data layout, we can only guarantee gem objects with handles are of the same gem object type as the main one in use by the driver. Signed-off-by: Lyude Paul --- drivers/gpu/drm/nova/gem.rs | 8 ++-- rust/kernel/drm/driver.rs | 3 ++ rust/kernel/drm/gem/mod.rs | 77 ++++++++++++++++--------------------- 3 files changed, 40 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs index cd82773dab92c..2760ba4f3450b 100644 --- a/drivers/gpu/drm/nova/gem.rs +++ b/drivers/gpu/drm/nova/gem.rs @@ -16,16 +16,14 @@ #[pin_data] pub(crate) struct NovaObject {} =20 -impl gem::BaseDriverObject> for NovaObject { +impl gem::DriverObject for NovaObject { + type Driver =3D NovaDriver; + fn new(_dev: &NovaDevice, _size: usize) -> impl PinInit { try_pin_init!(NovaObject {}) } } =20 -impl gem::DriverObject for NovaObject { - type Driver =3D NovaDriver; -} - impl NovaObject { /// Create a new DRM GEM object. pub(crate) fn new(dev: &NovaDevice, size: usize) -> Result>> { diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs index fe7e8d06961aa..dae0f4d1bbe3c 100644 --- a/rust/kernel/drm/driver.rs +++ b/rust/kernel/drm/driver.rs @@ -86,6 +86,9 @@ pub struct AllocOps { =20 /// Trait for memory manager implementations. Implemented internally. pub trait AllocImpl: super::private::Sealed + drm::gem::IntoGEMObject { + /// The [`Driver`] implementation for this [`AllocImpl`]. + type Driver: drm::Driver; + /// The C callback operations for this memory manager. const ALLOC_OPS: AllocOps; } diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index b71821cfb5eaa..31c5799d995c5 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -15,31 +15,31 @@ use core::{mem, ops::Deref, ptr::NonNull}; =20 /// GEM object functions, which must be implemented by drivers. -pub trait BaseDriverObject: Sync + Send + Sized { +pub trait DriverObject: Sync + Send + Sized { + /// Parent `Driver` for this object. + type Driver: drm::Driver; + /// Create a new driver data object for a GEM object of a given size. - fn new(dev: &drm::Device, size: usize) -> impl PinInit; + fn new(dev: &drm::Device, size: usize) -> impl PinInit; =20 /// Open a new handle to an existing object, associated with a File. fn open( - _obj: &<::Driver as drm::Driver>::Object, - _file: &drm::File<<::Driver as drm::Driver>::F= ile>, + _obj: &::Object, + _file: &drm::File<::File>, ) -> Result { Ok(()) } =20 /// Close a handle to an existing object, associated with a File. fn close( - _obj: &<::Driver as drm::Driver>::Object, - _file: &drm::File<<::Driver as drm::Driver>::F= ile>, + _obj: &::Object, + _file: &drm::File<::File>, ) { } } =20 /// Trait that represents a GEM object subtype pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted= { - /// Owning driver for this type - type Driver: drm::Driver; - /// Returns a reference to the raw `drm_gem_object` structure, which m= ust be valid as long as /// this owning object is valid. fn as_raw(&self) -> *mut bindings::drm_gem_object; @@ -74,25 +74,15 @@ unsafe fn dec_ref(obj: NonNull) { } } =20 -/// Trait which must be implemented by drivers using base GEM objects. -pub trait DriverObject: BaseDriverObject> { - /// Parent `Driver` for this object. - type Driver: drm::Driver; -} - -extern "C" fn open_callback, U: BaseObject>( +extern "C" fn open_callback( raw_obj: *mut bindings::drm_gem_object, raw_file: *mut bindings::drm_file, ) -> core::ffi::c_int { // SAFETY: `open_callback` is only ever called with a valid pointer to= a `struct drm_file`. - let file =3D unsafe { - drm::File::<<::Driver as drm::Driver>::File>::= from_raw(raw_file) - }; - // SAFETY: `open_callback` is specified in the AllocOps structure for = `Object`, ensuring that - // `raw_obj` is indeed contained within a `Object`. - let obj =3D unsafe { - <<::Driver as drm::Driver>::Object as IntoGEMO= bject>::from_raw(raw_obj) - }; + let file =3D unsafe { drm::File::<::File>::f= rom_raw(raw_file) }; + // SAFETY: `open_callback` is specified in the AllocOps structure for = `DriverObject`, + // ensuring that `raw_obj` is contained within a `DriverObject` + let obj =3D unsafe { <::Object as IntoGEMObj= ect>::from_raw(raw_obj) }; =20 match T::open(obj, file) { Err(e) =3D> e.to_errno(), @@ -100,26 +90,21 @@ extern "C" fn open_callback, U:= BaseObject>( } } =20 -extern "C" fn close_callback, U: BaseObject>( +extern "C" fn close_callback( raw_obj: *mut bindings::drm_gem_object, raw_file: *mut bindings::drm_file, ) { // SAFETY: `open_callback` is only ever called with a valid pointer to= a `struct drm_file`. - let file =3D unsafe { - drm::File::<<::Driver as drm::Driver>::File>::= from_raw(raw_file) - }; + let file =3D unsafe { drm::File::<::File>::f= rom_raw(raw_file) }; + // SAFETY: `close_callback` is specified in the AllocOps structure for= `Object`, ensuring // that `raw_obj` is indeed contained within a `Object`. - let obj =3D unsafe { - <<::Driver as drm::Driver>::Object as IntoGEMO= bject>::from_raw(raw_obj) - }; + let obj =3D unsafe { <::Object as IntoGEMObj= ect>::from_raw(raw_obj) }; =20 T::close(obj, file); } =20 impl IntoGEMObject for Object { - type Driver =3D T::Driver; - fn as_raw(&self) -> *mut bindings::drm_gem_object { self.obj.get() } @@ -141,10 +126,12 @@ fn size(&self) -> usize { =20 /// Creates a new handle for the object associated with a given `File` /// (or returns an existing one). - fn create_handle( - &self, - file: &drm::File<<::Driver as drm::Driver>:= :File>, - ) -> Result { + fn create_handle(&self, file: &drm::File) -> Result + where + Self: AllocImpl, + D: drm::Driver, + F: drm::file::DriverFile, + { let mut handle: u32 =3D 0; // SAFETY: The arguments are all valid per the type invariants. to_result(unsafe { @@ -154,10 +141,12 @@ fn create_handle( } =20 /// Looks up an object by its handle for a given `File`. - fn lookup_handle( - file: &drm::File<<::Driver as drm::Driver>:= :File>, - handle: u32, - ) -> Result> { + fn lookup_handle(file: &drm::File, handle: u32) -> Result> + where + Self: AllocImpl, + D: drm::Driver, + F: drm::file::DriverFile, + { // SAFETY: The arguments are all valid per the type invariants. let ptr =3D unsafe { bindings::drm_gem_object_lookup(file.as_raw()= .cast(), handle) }; if ptr.is_null() { @@ -212,8 +201,8 @@ impl Object { =20 const OBJECT_FUNCS: bindings::drm_gem_object_funcs =3D bindings::drm_g= em_object_funcs { free: Some(Self::free_callback), - open: Some(open_callback::>), - close: Some(close_callback::>), + open: Some(open_callback::), + close: Some(close_callback::), print_info: None, export: None, pin: None, @@ -296,6 +285,8 @@ fn deref(&self) -> &Self::Target { } =20 impl AllocImpl for Object { + type Driver =3D T::Driver; + const ALLOC_OPS: AllocOps =3D AllocOps { gem_create_object: None, prime_handle_to_fd: None, --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7ADCE2C21D5 for ; Fri, 29 Aug 2025 22:43:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507428; cv=none; b=onYOu/CJCWFE4DdZyRvU7XJZNs8sEnOuz8pCsqV14uAkssqBMNkjMIrgjp1agEeuOSLT9e5jPrf0sDAIEezY+Qrmz2Qf+COLYl7gKZKuSrusEpALvGfsdL35o6+yNdJ+itZ0wwjtSOt1oBflrRU5XQEI0keTXFOm+l0pdhQ4UHk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507428; c=relaxed/simple; bh=kzqGDyWPM45AEnQWZknAN3s48rr9rv65Xi6dreboiSs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=D4U1pBa1Nlsz+D2wENTL97yXBC6ugA7cso89oB60qH88UaEcVupQPTv69y83Lk7HSeaFGt+pOI4/q232ngDiH4bbHvqBU+EO7iFuzeHbPu4c0aQJumn/oVv7eqTFCyD4XWkYg0lb5p30x3JQo+2eivWPgyzWz+RQHAtlal17OuU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=V+z89RFG; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="V+z89RFG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507425; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+gdTOKk1/eH4mNU8bIQIDKd1Df4IdxKppBOHckOsbo8=; b=V+z89RFGfo+8t1rT0jRXrDmy6p1LLjQR6GnfFg8aDpLSJ7vq9ZpWHSla5d+BohijLaXXbF rABDP5q6suCkr8p9s7U/J4GJVKDRIcVjYOIHATAjSqwEdaC2RMqAHpO5u/Lrl/0KJ2tHja de2KLu39URYKxtXuDEqN1nWRgys6ACw= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-161-ZGNqGcuWNoi4PuuZYo_gnw-1; Fri, 29 Aug 2025 18:41:46 -0400 X-MC-Unique: ZGNqGcuWNoi4PuuZYo_gnw-1 X-Mimecast-MFC-AGG-ID: ZGNqGcuWNoi4PuuZYo_gnw_1756507304 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B77E519560A6; Fri, 29 Aug 2025 22:41:43 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1D2DC1800280; Fri, 29 Aug 2025 22:41:38 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Asahi Lina Subject: [PATCH v3 02/14] rust: drm: gem: Add DriverFile type alias Date: Fri, 29 Aug 2025 18:35:17 -0400 Message-ID: <20250829224116.477990-3-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Just to reduce the clutter with the File<=E2=80=A6> types in gem.rs. Signed-off-by: Lyude Paul Reviewed-by: Daniel Almeida --- V3: * Rename ObjectFile to DriverFile Signed-off-by: Lyude Paul --- rust/kernel/drm/gem/mod.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index 31c5799d995c5..80940ed11368d 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -14,6 +14,13 @@ }; use core::{mem, ops::Deref, ptr::NonNull}; =20 +/// A type alias for retrieving a [`Driver`]s [`DriverFile`] implementatio= n from its +/// [`DriverObject`] implementation. +/// +/// [`Driver`]: drm::Driver +/// [`DriverFile`]: drm::file::DriverFile +pub type DriverFile =3D drm::File<<::Driver as drm::= Driver>::File>; + /// GEM object functions, which must be implemented by drivers. pub trait DriverObject: Sync + Send + Sized { /// Parent `Driver` for this object. @@ -23,19 +30,12 @@ pub trait DriverObject: Sync + Send + Sized { fn new(dev: &drm::Device, size: usize) -> impl PinInit; =20 /// Open a new handle to an existing object, associated with a File. - fn open( - _obj: &::Object, - _file: &drm::File<::File>, - ) -> Result { + fn open(_obj: &::Object, _file: &DriverFi= le) -> Result { Ok(()) } =20 /// Close a handle to an existing object, associated with a File. - fn close( - _obj: &::Object, - _file: &drm::File<::File>, - ) { - } + fn close(_obj: &::Object, _file: &DriverF= ile) {} } =20 /// Trait that represents a GEM object subtype @@ -79,7 +79,8 @@ extern "C" fn open_callback( raw_file: *mut bindings::drm_file, ) -> core::ffi::c_int { // SAFETY: `open_callback` is only ever called with a valid pointer to= a `struct drm_file`. - let file =3D unsafe { drm::File::<::File>::f= rom_raw(raw_file) }; + let file =3D unsafe { DriverFile::::from_raw(raw_file) }; + // SAFETY: `open_callback` is specified in the AllocOps structure for = `DriverObject`, // ensuring that `raw_obj` is contained within a `DriverObject` let obj =3D unsafe { <::Object as IntoGEMObj= ect>::from_raw(raw_obj) }; @@ -95,7 +96,7 @@ extern "C" fn close_callback( raw_file: *mut bindings::drm_file, ) { // SAFETY: `open_callback` is only ever called with a valid pointer to= a `struct drm_file`. - let file =3D unsafe { drm::File::<::File>::f= rom_raw(raw_file) }; + let file =3D unsafe { DriverFile::::from_raw(raw_file) }; =20 // SAFETY: `close_callback` is specified in the AllocOps structure for= `Object`, ensuring // that `raw_obj` is indeed contained within a `Object`. --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B6AE2C1597 for ; Fri, 29 Aug 2025 22:42:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507323; cv=none; b=iaosNBClaOBdKNSAQjZrCcfbKunvwUosZvY4eFzhrAF2YC21vcfrkHn7oClwcQBgjPAwd7ui/ijJ0F5FVlmfd7/Aj38ewal6zN+Wza75eSLw5ooze+J+/Q6MHZANaX0JmxRTRIRdVJAGVhxewSVAHeeC9ITGrJhThVtF0RUs2e8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507323; c=relaxed/simple; bh=OE1X0P/a5ccHP7szvuz/09fZvwZpoEOQ/1G2+CUnG6A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NDQpTs+pIW5wK/e1UNc5IQXeImuy6k4kAZ1gVeX5MwEFyTJbFV4+l8ulNHE+s03i3WsOTnp/E3iHJ08DKIa9YiGCMvrx2/JOs/I8B3CXWeN5/gRZkBgm+YXSGNI/CmUv9cslqvEofPRp8ujcZX3rvgHTZElw8ef9cmDAKgtUsu0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=iVtc3LvW; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="iVtc3LvW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507320; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OTgut8Xsr5lgOiY155i03UDPgzXuKzvVXZDRWRhboac=; b=iVtc3LvWVsh82Mdt+2aQMRzZ7WPQtI+D2aicn4quwBFsQiv1SRo4LIpz0bTxro2YK2hcEP daTr/tcHajIFG6BwHiK1MaPckGJGNlNMTjxXG7nzhvk75lqht9MHr154dea/iGg4Lmqsxg 7TA4+2ufsdSStHInnOPtpthmEj+j3UE= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-688-P12YGXJQMBCF1DKRJ4vo8A-1; Fri, 29 Aug 2025 18:41:54 -0400 X-MC-Unique: P12YGXJQMBCF1DKRJ4vo8A-1 X-Mimecast-MFC-AGG-ID: P12YGXJQMBCF1DKRJ4vo8A_1756507311 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 37C6E1956089; Fri, 29 Aug 2025 22:41:51 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DD07E18003FC; Fri, 29 Aug 2025 22:41:46 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Danilo Krummrich , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Asahi Lina Subject: [PATCH v3 03/14] rust: drm: gem: Drop Object::SIZE Date: Fri, 29 Aug 2025 18:35:18 -0400 Message-ID: <20250829224116.477990-4-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Drive-by fix, it doesn't seem like anything actually uses this constant anymore. Signed-off-by: Lyude Paul Reviewed-by: Danilo Krummrich Reviewed-by: Daniel Almeida --- rust/kernel/drm/gem/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index 80940ed11368d..b27b9fbf28bbb 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -12,7 +12,7 @@ prelude::*, types::{ARef, AlwaysRefCounted, Opaque}, }; -use core::{mem, ops::Deref, ptr::NonNull}; +use core::{ops::Deref, ptr::NonNull}; =20 /// A type alias for retrieving a [`Driver`]s [`DriverFile`] implementatio= n from its /// [`DriverObject`] implementation. @@ -197,9 +197,6 @@ pub struct Object { } =20 impl Object { - /// The size of this object's structure. - pub const SIZE: usize =3D mem::size_of::(); - const OBJECT_FUNCS: bindings::drm_gem_object_funcs =3D bindings::drm_g= em_object_funcs { free: Some(Self::free_callback), open: Some(open_callback::), --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 946022D2389 for ; Fri, 29 Aug 2025 22:42:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507330; cv=none; b=t4Ria5gholK/ZTToCIAwwgXz3G13KfrzMnOzKP70JR57KqIfVmQU35qad+p+TRtPqKHf4ad2ezGqLxv9oSuW6O4CTf+MEgHvDvbv/oibJAyNbKn358bdBM+S98LC2q5c8DpQAtBQZo7j+DaV3g4PUUad3SUY37cAFxwB6L9+0zQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507330; c=relaxed/simple; bh=mUwK/xsFfwuzsq3kyWVjdRlk2pq182o2/gqikyETILc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tdvWoT6jBPXjsICMBsl8u1EkuAqLLUCAZVw3Z4MeRwbWiPL/NX35z3DLJxaRZvmxzl4chI54zWMWxIlaOw+VOXKOz7K1gL6DxbqarcF0gfweUe29Y5BhRD0mxwVspb2+LarvPQawNgcq5nUQhsfFP+zhMVyUojZP/SOSVgrwYMY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=eieRm8NN; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="eieRm8NN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507327; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cr7Z5SnqFnSoE6cxmV2l32qPVo05acQnlSmqa8BLLuw=; b=eieRm8NNr4yi80OnciFcsQt8ChXMs2pmToB0lB9sbxV5HoBeRA+rx+vWnrOLgfvSzWsvKG 7llfDJVhJwqhWv5nYpb4DkZMwPyc7LrYHPsuHxOLgSKGhsCMd5lSTl4gab7IgaDHPMA3fH Mw2FGytCXCC8+WgHOmItwHRllrwT0Ws= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-114-IJgjwKlTMvOBSB8COVyeAw-1; Fri, 29 Aug 2025 18:42:02 -0400 X-MC-Unique: IJgjwKlTMvOBSB8COVyeAw-1 X-Mimecast-MFC-AGG-ID: IJgjwKlTMvOBSB8COVyeAw_1756507319 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 19F231800451; Fri, 29 Aug 2025 22:41:59 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A091518003FC; Fri, 29 Aug 2025 22:41:54 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Asahi Lina , nouveau@lists.freedesktop.org (open list:DRM DRIVER FOR NVIDIA GPUS [RUST]) Subject: [PATCH v3 04/14] rust: drm: gem: Support driver-private GEM object types Date: Fri, 29 Aug 2025 18:35:19 -0400 Message-ID: <20250829224116.477990-5-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" One of the original intents with the gem bindings was that drivers could specify additional gem implementations, in order to enable for driver private gem objects. This wasn't really possible however, as up until now our GEM bindings have always assumed that the only GEM object we would run into was driver::Driver::Object - meaning that implementing another GEM object type would result in all of the BaseDriverObject callbacks assuming the wrong type. This is a pretty easy fix though, all we need to do is specify a BaseDriverObject in driver::Driver instead of an AllocImpl, and then add an associated type for AllocImpl in BaseDriverObject. That way each BaseDriverObject has its own AllocImpl allowing it to know which type to provide in BaseDriverObject callbacks, and driver::Driver can simply go through the BaseDriverObject to its AllocImpl type in order to get access to ALLOC_OPS. So, let's do this and update Nova for these changes. Signed-off-by: Lyude Paul --- V4: * Update trait bounds. This looks gnarlier then it is: Self: AllocImpl, <-- Get the driver for this GEM object D: drm::Driver, <-- Get the driver's Object, = File impl F: drm::file::DriverFile, O: BaseDriverObject, <-- Make sure we're the driver's main GEM object impl. (don't worry, the compiler can always figure out what D, F, O are) * Also, rename the commit. I realized I should be clearer about what this does so people can stop me if this isn't what was meant by private gem object implementations :). Signed-off-by: Lyude Paul --- drivers/gpu/drm/nova/driver.rs | 8 ++++++-- drivers/gpu/drm/nova/gem.rs | 1 + rust/kernel/drm/device.rs | 17 ++++++++++------- rust/kernel/drm/driver.rs | 2 +- rust/kernel/drm/gem/mod.rs | 21 +++++++++++++-------- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs index 91b7380f83ab4..4c252426056c5 100644 --- a/drivers/gpu/drm/nova/driver.rs +++ b/drivers/gpu/drm/nova/driver.rs @@ -1,7 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 =20 use kernel::{ - auxiliary, c_str, device::Core, drm, drm::gem, drm::ioctl, prelude::*,= sync::aref::ARef, + auxiliary, c_str, + device::Core, + drm::{self, gem, ioctl}, + prelude::*, + types::ARef, }; =20 use crate::file::File; @@ -59,7 +63,7 @@ fn probe(adev: &auxiliary::Device, _info: &Self::Id= Info) -> Result; + type Object =3D NovaObject; =20 const INFO: drm::DriverInfo =3D INFO; =20 diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs index 2760ba4f3450b..10e3053f1a246 100644 --- a/drivers/gpu/drm/nova/gem.rs +++ b/drivers/gpu/drm/nova/gem.rs @@ -18,6 +18,7 @@ pub(crate) struct NovaObject {} =20 impl gem::DriverObject for NovaObject { type Driver =3D NovaDriver; + type Object =3D gem::Object; =20 fn new(_dev: &NovaDevice, _size: usize) -> impl PinInit { try_pin_init!(NovaObject {}) diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs index 3bb7c83966cf2..16cf6cb53d9a7 100644 --- a/rust/kernel/drm/device.rs +++ b/rust/kernel/drm/device.rs @@ -60,6 +60,9 @@ pub struct Device { data: T::Data, } =20 +/// A type alias for referring to the [`AllocImpl`] implementation for a D= RM driver. +type DriverAllocImpl =3D <::Object as drm::gem::Drive= rObject>::Object; + impl Device { const VTABLE: bindings::drm_driver =3D drm_legacy_fields! { load: None, @@ -70,13 +73,13 @@ impl Device { master_set: None, master_drop: None, debugfs_init: None, - gem_create_object: T::Object::ALLOC_OPS.gem_create_object, - prime_handle_to_fd: T::Object::ALLOC_OPS.prime_handle_to_fd, - prime_fd_to_handle: T::Object::ALLOC_OPS.prime_fd_to_handle, - gem_prime_import: T::Object::ALLOC_OPS.gem_prime_import, - gem_prime_import_sg_table: T::Object::ALLOC_OPS.gem_prime_import_s= g_table, - dumb_create: T::Object::ALLOC_OPS.dumb_create, - dumb_map_offset: T::Object::ALLOC_OPS.dumb_map_offset, + gem_create_object: DriverAllocImpl::::ALLOC_OPS.gem_create_obje= ct, + prime_handle_to_fd: DriverAllocImpl::::ALLOC_OPS.prime_handle_t= o_fd, + prime_fd_to_handle: DriverAllocImpl::::ALLOC_OPS.prime_fd_to_ha= ndle, + gem_prime_import: DriverAllocImpl::::ALLOC_OPS.gem_prime_import, + gem_prime_import_sg_table: DriverAllocImpl::::ALLOC_OPS.gem_pri= me_import_sg_table, + dumb_create: DriverAllocImpl::::ALLOC_OPS.dumb_create, + dumb_map_offset: DriverAllocImpl::::ALLOC_OPS.dumb_map_offset, show_fdinfo: None, fbdev_probe: None, =20 diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs index dae0f4d1bbe3c..2500a61f45a6a 100644 --- a/rust/kernel/drm/driver.rs +++ b/rust/kernel/drm/driver.rs @@ -103,7 +103,7 @@ pub trait Driver { type Data: Sync + Send; =20 /// The type used to manage memory for this driver. - type Object: AllocImpl; + type Object: drm::gem::DriverObject; =20 /// The type used to represent a DRM File (client) type File: drm::file::DriverFile; diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index b27b9fbf28bbb..ec36cd9ea69ed 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -26,16 +26,19 @@ pub trait DriverObject: Sync + Send + Sized { /// Parent `Driver` for this object. type Driver: drm::Driver; =20 + /// The GEM object type that will be passed to various callbacks. + type Object: AllocImpl; + /// Create a new driver data object for a GEM object of a given size. fn new(dev: &drm::Device, size: usize) -> impl PinInit; =20 /// Open a new handle to an existing object, associated with a File. - fn open(_obj: &::Object, _file: &DriverFi= le) -> Result { + fn open(_obj: &Self::Object, _file: &DriverFile) -> Result { Ok(()) } =20 /// Close a handle to an existing object, associated with a File. - fn close(_obj: &::Object, _file: &DriverF= ile) {} + fn close(_obj: &Self::Object, _file: &DriverFile) {} } =20 /// Trait that represents a GEM object subtype @@ -83,7 +86,7 @@ extern "C" fn open_callback( =20 // SAFETY: `open_callback` is specified in the AllocOps structure for = `DriverObject`, // ensuring that `raw_obj` is contained within a `DriverObject` - let obj =3D unsafe { <::Object as IntoGEMObj= ect>::from_raw(raw_obj) }; + let obj =3D unsafe { T::Object::from_raw(raw_obj) }; =20 match T::open(obj, file) { Err(e) =3D> e.to_errno(), @@ -100,7 +103,7 @@ extern "C" fn close_callback( =20 // SAFETY: `close_callback` is specified in the AllocOps structure for= `Object`, ensuring // that `raw_obj` is indeed contained within a `Object`. - let obj =3D unsafe { <::Object as IntoGEMObj= ect>::from_raw(raw_obj) }; + let obj =3D unsafe { T::Object::from_raw(raw_obj) }; =20 T::close(obj, file); } @@ -127,11 +130,12 @@ fn size(&self) -> usize { =20 /// Creates a new handle for the object associated with a given `File` /// (or returns an existing one). - fn create_handle(&self, file: &drm::File) -> Result + fn create_handle(&self, file: &drm::File) -> Result where Self: AllocImpl, - D: drm::Driver, + D: drm::Driver, F: drm::file::DriverFile, + O: DriverObject, { let mut handle: u32 =3D 0; // SAFETY: The arguments are all valid per the type invariants. @@ -142,11 +146,12 @@ fn create_handle(&self, file: &drm::File) ->= Result } =20 /// Looks up an object by its handle for a given `File`. - fn lookup_handle(file: &drm::File, handle: u32) -> Result> + fn lookup_handle(file: &drm::File, handle: u32) -> Result<= ARef> where Self: AllocImpl, - D: drm::Driver, + D: drm::Driver, F: drm::file::DriverFile, + O: DriverObject, { // SAFETY: The arguments are all valid per the type invariants. let ptr =3D unsafe { bindings::drm_gem_object_lookup(file.as_raw()= .cast(), handle) }; --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A8DE72D660A for ; Fri, 29 Aug 2025 22:42:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507336; cv=none; b=Tp8rX6q0CWGTCT2FOZBEfP6f1sIJBelvDHnuXxuBXJ4+FBhGD9MCvspcztt4BvEGyl88ckBj0NwM1uWd/4Y8HT7yV10tr/n63QxonmUA05hvxGO2aE5Nri7bcsJ6y5fKuCD/xQ0s5MHnarZf3CGL0A0npZKnEFBSF0rOCF2rJOk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507336; c=relaxed/simple; bh=U8UnERAkfxzUAjGAE7pOlGorLb2FYdbdJBYSzttv4aQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KGzhIykQVRnNmFkaMia1URw46t5snVnORkRMCdKQW41HuNjndDmSjqeox8lNRBGwY7v6z2qgSNT+0Dm9HXgQDTMff5tjaB6VnAa6wqpZV7hi7zpbvsa6ahf//+xKGpztKtNxBYvoukRla6GKJXZNS6uflnasyzKxg9vWFfLyB+8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ipnLxohC; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ipnLxohC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507333; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IKybner1GmKgcTnqqF43UsfxL3oL5QNO4lMcxBfIxqQ=; b=ipnLxohCrhmzESf7kEJMr7f9/peZMlnl4A5MGsdEdMK/ww8ZSYJexURX1X9x+j+bS4Epq+ y27o23sDoPzdLrtmmIG+lccYzZUNsiDXI9mcsEz+ICzG8TYQNqZjUYWow/aMOTRmd8OSV7 AP7Lh4LInGvIBrnjnAFuVQZ3VQaDrrQ= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-272-HVLOyX7aO1u5bu5ue-B6og-1; Fri, 29 Aug 2025 18:42:11 -0400 X-MC-Unique: HVLOyX7aO1u5bu5ue-B6og-1 X-Mimecast-MFC-AGG-ID: HVLOyX7aO1u5bu5ue-B6og_1756507327 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 176841800347; Fri, 29 Aug 2025 22:42:07 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A460518003FC; Fri, 29 Aug 2025 22:42:01 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Asahi Lina , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , Greg Kroah-Hartman , Asahi Lina , Viresh Kumar , Daniel Almeida , Wedson Almeida Filho , FUJITA Tomonori , Krishna Ketan Rai , linux-media@vger.kernel.org (open list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b), linaro-mm-sig@lists.linaro.org (moderated list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b) Subject: [PATCH v3 05/14] rust: helpers: Add bindings/wrappers for dma_resv_lock Date: Fri, 29 Aug 2025 18:35:20 -0400 Message-ID: <20250829224116.477990-6-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" From: Asahi Lina This is just for basic usage in the DRM shmem abstractions for implied locking, not intended as a full DMA Reservation abstraction yet. Signed-off-by: Asahi Lina Signed-off-by: Daniel Almeida Signed-off-by: Lyude Paul --- rust/bindings/bindings_helper.h | 1 + rust/helpers/dma-resv.c | 13 +++++++++++++ rust/helpers/helpers.c | 1 + 3 files changed, 15 insertions(+) create mode 100644 rust/helpers/dma-resv.c diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index c2cc52ee9945b..00fe0449ed6de 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/dma-resv.c b/rust/helpers/dma-resv.c new file mode 100644 index 0000000000000..05501cb814513 --- /dev/null +++ b/rust/helpers/dma-resv.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +int rust_helper_dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx = *ctx) +{ + return dma_resv_lock(obj, ctx); +} + +void rust_helper_dma_resv_unlock(struct dma_resv *obj) +{ + dma_resv_unlock(obj); +} diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index e94542bf6ea74..77354382fbea0 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -20,6 +20,7 @@ #include "cred.c" #include "device.c" #include "dma.c" +#include "dma-resv.c" #include "drm.c" #include "err.c" #include "fs.c" --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6647E2D0C67 for ; Fri, 29 Aug 2025 22:42:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507371; cv=none; b=hj6vOUgh2hpLUejwf2YCHImP/cV7hvDYQn0JIvRUqMWz2XVCdukSp72zEid1ceRqEdFZjMmp3wFGSKnJBVB8aUQgU5O6piUjp6EQgfpkcq8X5VuWtdA77CPk+wRbN18bC8YVPBQp6nChTmgZAkduoSR+zV9eQq7DjGAASPoPLHk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507371; c=relaxed/simple; bh=OlP8MYcLYn8B4Ppd94bua5MQUc1xpc8AUyxsAK6NMps=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Zf71sNzBqyR4h0Syh0uFAHjZ/T3kK+6nHkkVfVTrkcOoH4zv7NqBBnROlqSoEOscE42G7OCxP04J27DhvWnVOSbkbZcRdEdNaGoi/dwdEXCuRXjJeE/TKRkIOS67h+Feu12L/zXgvKSJQU81sNf4du2vM/JG580Aef/9quB36Ic= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=YHnKKJ8r; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="YHnKKJ8r" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507369; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yXnTUIqS+LiZwSLAb4BzQOkRqLb5m0E0Ss24acMrZZE=; b=YHnKKJ8rNIlDp0pL+4Lh1+tXoWeEm88GwMsIY598NGk+n/cIx3/X7KDc/0M4qWtun60eYJ 07vzCsz2j4FuiT/fTnm/ippW/epZ5DLq85H+2AMo2ynGmkdSi1NSn20DjekQuLF4GMsjzI WpY+Gq90rYnMxH7Iun9pkSN3lPygnQ4= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-36-CMFgr5AvMk-4CX6S-X9AhA-1; Fri, 29 Aug 2025 18:42:18 -0400 X-MC-Unique: CMFgr5AvMk-4CX6S-X9AhA-1 X-Mimecast-MFC-AGG-ID: CMFgr5AvMk-4CX6S-X9AhA_1756507335 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6069719560B5; Fri, 29 Aug 2025 22:42:15 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 558801800280; Fri, 29 Aug 2025 22:42:10 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , Daniel Almeida , Asahi Lina , linux-media@vger.kernel.org (open list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b), linaro-mm-sig@lists.linaro.org (moderated list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b) Subject: [PATCH v3 06/14] rust: drm: gem: Add raw_dma_resv() function Date: Fri, 29 Aug 2025 18:35:21 -0400 Message-ID: <20250829224116.477990-7-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" For retrieving a pointer to the struct dma_resv for a given GEM object. We also introduce it in a new trait, BaseObjectPrivate, which we automatically implement for all gem objects and don't expose to users outside of the crate. Signed-off-by: Lyude Paul --- rust/kernel/drm/gem/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index ec36cd9ea69ed..f901d4263ee87 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -186,6 +186,18 @@ fn create_mmap_offset(&self) -> Result { =20 impl BaseObject for T {} =20 +/// Crate-private base operations shared by all GEM object classes. +#[expect(unused)] +pub(crate) trait BaseObjectPrivate: IntoGEMObject { + /// Return a pointer to this object's dma_resv. + fn raw_dma_resv(&self) -> *mut bindings::dma_resv { + // SAFETY: `as_gem_obj()` always returns a valid pointer to the ba= se DRM gem object + unsafe { (*self.as_raw()).resv } + } +} + +impl BaseObjectPrivate for T {} + /// A base GEM object. /// /// Invariants --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E523C2D29B7 for ; Fri, 29 Aug 2025 22:42:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507348; cv=none; b=SXpaWwVeBD2mWYpwy08pSrd56EX3+XLQYF93o1bDvp+Bzk901nqUtaC0p6Wxja0Ep1vN0pwUTPLSpP/0xME8AU44Zfr+rh4tbSf5cQbGris6MrEQRiZdITSjynfSOrlGoowMiLkbVQJC80Oz2xktWalOCKapP2Y9St5q+jKcsrs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507348; c=relaxed/simple; bh=qY/WS+JSzXrJnz13P2JycsR7uLx5XYUmvceIg8mJwsk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IVGlw4EepqCNZB3e/fUeZkMHJi+0P/cvH+a6zYg5PmBddo341+wjmPiKH6qME7LM87rk11bSnsv4e7N4D2sjY/+U9Mj3fOVqbpDkWKszX/wKCr2SEkv68QonuA2qLi60+wvYku8jVOkr66xWX+TyhXYI7Ieq6MnJtJYviz+0aBk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=bAXa1INn; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="bAXa1INn" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507346; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=S1Fhz1PTXOhmZ8djwZv/67nKgTEm9xnLnTdr5xEBKlk=; b=bAXa1INnTF+PUyBe7CQQUqrta+LJ5WfS3BwsohcVFX5kX/2XVDM9sUV6VdDs38O8ESyM71 xP0wtjN466N3uWattLfvTOP5N6VH+ch/e9YVlnyvObxUX0v62jyJvuz/qIiztKRTfeSXB4 SNzBdPUFuwYHpF0MoaCSRqLa4XMknrM= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-260-PvsJbcGfNmKepUYhN4D37A-1; Fri, 29 Aug 2025 18:42:22 -0400 X-MC-Unique: PvsJbcGfNmKepUYhN4D37A-1 X-Mimecast-MFC-AGG-ID: PvsJbcGfNmKepUYhN4D37A_1756507339 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7EAE418003FC; Fri, 29 Aug 2025 22:42:19 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D714E1800447; Fri, 29 Aug 2025 22:42:15 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [PATCH v3 07/14] drm/gem/shmem: Extract drm_gem_shmem_init() from drm_gem_shmem_create() Date: Fri, 29 Aug 2025 18:35:22 -0400 Message-ID: <20250829224116.477990-8-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" With gem objects in rust, the most ideal way for us to be able to handle gem shmem object creation is to be able to handle the memory allocation of a gem object ourselves - and then have the DRM gem shmem helpers initialize the object we've allocated afterwards. So, let's spit out drm_gem_shmem_init() from drm_gem_shmem_create() to allow for doing this. Signed-off-by: Lyude Paul Reviewed-by: Daniel Almeida --- drivers/gpu/drm/drm_gem_shmem_helper.c | 75 +++++++++++++++++--------- include/drm/drm_gem_shmem_helper.h | 1 + 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_g= em_shmem_helper.c index 5d1349c34afd3..b20a7b75c7228 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -48,28 +48,12 @@ static const struct drm_gem_object_funcs drm_gem_shmem_= funcs =3D { .vm_ops =3D &drm_gem_shmem_vm_ops, }; =20 -static struct drm_gem_shmem_object * -__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private, - struct vfsmount *gemfs) +static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shm= em_object *shmem, + size_t size, bool private, struct vfsmount *gemfs) { - struct drm_gem_shmem_object *shmem; - struct drm_gem_object *obj; + struct drm_gem_object *obj =3D &shmem->base; int ret =3D 0; =20 - size =3D PAGE_ALIGN(size); - - if (dev->driver->gem_create_object) { - obj =3D dev->driver->gem_create_object(dev, size); - if (IS_ERR(obj)) - return ERR_CAST(obj); - shmem =3D to_drm_gem_shmem_obj(obj); - } else { - shmem =3D kzalloc(sizeof(*shmem), GFP_KERNEL); - if (!shmem) - return ERR_PTR(-ENOMEM); - obj =3D &shmem->base; - } - if (!obj->funcs) obj->funcs =3D &drm_gem_shmem_funcs; =20 @@ -81,7 +65,7 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t siz= e, bool private, } if (ret) { drm_gem_private_object_fini(obj); - goto err_free; + return ret; } =20 ret =3D drm_gem_create_mmap_offset(obj); @@ -102,14 +86,55 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t = size, bool private, __GFP_RETRY_MAYFAIL | __GFP_NOWARN); } =20 - return shmem; - + return 0; err_release: drm_gem_object_release(obj); -err_free: - kfree(obj); + return ret; +} =20 - return ERR_PTR(ret); +/** + * drm_gem_shmem_init - Initialize an allocated object. + * @dev: DRM device + * @obj: The allocated shmem GEM object. + * + * Returns: + * 0 on success, or a negative error code on failure. + */ +int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object= *shmem, size_t size) +{ + return __drm_gem_shmem_init(dev, shmem, size, false, NULL); +} +EXPORT_SYMBOL_GPL(drm_gem_shmem_init); + +static struct drm_gem_shmem_object * +__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private, + struct vfsmount *gemfs) +{ + struct drm_gem_shmem_object *shmem; + struct drm_gem_object *obj; + int ret =3D 0; + + size =3D PAGE_ALIGN(size); + + if (dev->driver->gem_create_object) { + obj =3D dev->driver->gem_create_object(dev, size); + if (IS_ERR(obj)) + return ERR_CAST(obj); + shmem =3D to_drm_gem_shmem_obj(obj); + } else { + shmem =3D kzalloc(sizeof(*shmem), GFP_KERNEL); + if (!shmem) + return ERR_PTR(-ENOMEM); + obj =3D &shmem->base; + } + + ret =3D __drm_gem_shmem_init(dev, shmem, size, private, gemfs); + if (ret) { + kfree(obj); + return ERR_PTR(ret); + } + + return shmem; } /** * drm_gem_shmem_create - Allocate an object with the given size diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem= _helper.h index 92f5db84b9c22..235dc33127b9a 100644 --- a/include/drm/drm_gem_shmem_helper.h +++ b/include/drm/drm_gem_shmem_helper.h @@ -107,6 +107,7 @@ struct drm_gem_shmem_object { #define to_drm_gem_shmem_obj(obj) \ container_of(obj, struct drm_gem_shmem_object, base) =20 +int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object= *shmem, size_t size); struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, = size_t size); struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_devi= ce *dev, size_t size, --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82F8B2D8381 for ; Fri, 29 Aug 2025 22:42:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507355; cv=none; b=HbNWYmpr7aZM6LA73EESlwPVhau5pL7HEucL5qH3QyQda/i/e7jEsrdcJb+GOwBihsR0FDcdyFNgM7a4ZLawlzqO80kkao9+/fdQcdJkOFxSwA4kNiuHCdgtNdm9zmPuNZ+ZmH/G6EkqSqvSL4R0Hb+a8Dwcj/UIZfs2DE9TsrU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507355; c=relaxed/simple; bh=iLaDtpubQ3yFSxlFHwnSPrbBmSc/n7SRhDXXmqcJ5Cw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HFozH2oJuZBXDATWzO36YQgni8Q9wxViE59yq2SFdKMVskN5fYe1Zt5O+YhdglJU80KFWJ1rCFmMQIimgAAp/z+wAG3w+W101fFiik05b1+4vz78qYhmuZRJ6SwR0OO2c3BQzskF3RAukecKEv8Rs/BareFJuqmA5bldyF1mEe4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=BkWyHfaD; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="BkWyHfaD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507352; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CFSZNST5duWLIhbj/eS+ZDxBrcrRDSRdFnWdf10qxmk=; b=BkWyHfaDU/EVeGfOEm6IZp8JJgZfFL5q+ksRDiDZ25+TpU4zs2/aADm1ssnyseoudOlH01 c79/q48LkiDLHgrJwNFknTDDjgKJsPmSJZ29UhEBgUqJ5iOCCBCLt6mPGCpsqjMpqqG9Jx vtKdgPFhKaP2KPgoxMm2zWtvYlpOHMI= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-76-V6LUbupkMjmau9Issj1dWQ-1; Fri, 29 Aug 2025 18:42:26 -0400 X-MC-Unique: V6LUbupkMjmau9Issj1dWQ-1 X-Mimecast-MFC-AGG-ID: V6LUbupkMjmau9Issj1dWQ_1756507343 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D0EDF1800342; Fri, 29 Aug 2025 22:42:23 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 133DD18003FC; Fri, 29 Aug 2025 22:42:19 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich Subject: [PATCH v3 08/14] drm/gem/shmem: Extract drm_gem_shmem_release() from drm_gem_shmem_free() Date: Fri, 29 Aug 2025 18:35:23 -0400 Message-ID: <20250829224116.477990-9-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" At the moment the way that freeing gem shmem objects is not ideal for rust bindings. drm_gem_shmem_free() releases all of the associated memory with a gem shmem object with kfree(), which means that for us to correctly release a gem shmem object in rust we have to manually drop all of the contents of our gem object structure in-place by hand before finally calling drm_gem_shmem_free() to release the shmem resources and the allocation for the gem object. Since the only reason this is an issue is because of drm_gem_shmem_free() calling kfree(), we can fix this by splitting drm_gem_shmem_free() out into itself and drm_gem_shmem_release(), where drm_gem_shmem_release() releases the various gem shmem resources without freeing the structure itself. With this, we can safely re-acquire the KBox for the gem object's memory allocation and let rust handle cleaning up all of the other struct members automatically. Signed-off-by: Lyude Paul Reviewed-by: Daniel Almeida --- drivers/gpu/drm/drm_gem_shmem_helper.c | 23 ++++++++++++++++++----- include/drm/drm_gem_shmem_helper.h | 1 + 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_g= em_shmem_helper.c index b20a7b75c7228..50594cf8e17cc 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -175,13 +175,13 @@ struct drm_gem_shmem_object *drm_gem_shmem_create_wit= h_mnt(struct drm_device *de EXPORT_SYMBOL_GPL(drm_gem_shmem_create_with_mnt); =20 /** - * drm_gem_shmem_free - Free resources associated with a shmem GEM object - * @shmem: shmem GEM object to free + * drm_gem_shmem_release - Release resources associated with a shmem GEM o= bject. + * @shmem: shmem GEM object * - * This function cleans up the GEM object state and frees the memory used = to - * store the object itself. + * This function cleans up the GEM object state, but does not free the mem= ory used to store the + * object itself. This function is meant to be a dedicated helper for the = Rust GEM bindings. */ -void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem) +void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem) { struct drm_gem_object *obj =3D &shmem->base; =20 @@ -208,6 +208,19 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *s= hmem) } =20 drm_gem_object_release(obj); +} +EXPORT_SYMBOL_GPL(drm_gem_shmem_release); + +/** + * drm_gem_shmem_free - Free resources associated with a shmem GEM object + * @shmem: shmem GEM object to free + * + * This function cleans up the GEM object state and frees the memory used = to + * store the object itself. + */ +void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem) +{ + drm_gem_shmem_release(shmem); kfree(shmem); } EXPORT_SYMBOL_GPL(drm_gem_shmem_free); diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem= _helper.h index 235dc33127b9a..589f7bfe7506e 100644 --- a/include/drm/drm_gem_shmem_helper.h +++ b/include/drm/drm_gem_shmem_helper.h @@ -112,6 +112,7 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struc= t drm_device *dev, size_t struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_devi= ce *dev, size_t size, struct vfsmount *gemfs); +void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem); void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem); =20 void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem); --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 761212D9485 for ; Fri, 29 Aug 2025 22:42:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507361; cv=none; b=s36ySlxU++FVcwLhOBVPoqdVoBGI5/TjOqtLGjRb7gUbMw4FN5DAnx50D37WtFZ+bxELeCuNUEgwBsomOAd64HoEfedtxZFooOOETstG83zzIMT/pEy12lj8lLrK7mRaQPIUITEUyBpISh4Mh3iIvyon4IYxZv+GEGWg5AqG9r0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507361; c=relaxed/simple; bh=EtUsR3n0ijhYX7N98y4g5s32rGilNcHAFZRsCaZ/L7w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YF0tWXbGHui2KI9clLQQvVEKoUY86sE5AzdaFYSGyatSmRp+fKJnfBEWfEbRyZUa1aU/kgFLpS+S1x+876f4HOXcQCOoqGiRJyfhkRXjoE8si7D+/XvMkHewmZGViCLn77jBzFxbIOs1SEI2d8qyN3D+8O+hIuStR7+ZwW4o22A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=WgpYD7g3; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="WgpYD7g3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507358; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8XT8+KxxRjgfrj31cXlfL66GVxfKzDgbyTpTZPzgyGw=; b=WgpYD7g3lGtBqrfg51gsAUbGG47NIaTgr1hgHYhO80KdKNzx/Qo/CviLMaYogCtnwzpJTs TGIyehPRk1/01ejGyIk7XUXFQWw0ImvY14VdDe0TsNCBBApHSfGQZXDjdVvpOadtKOIlkc qKOOpFZCZn2zeCZiB5onrZX0klkVyEQ= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-687-gL577qKcMpaQEaDutDZZkw-1; Fri, 29 Aug 2025 18:42:34 -0400 X-MC-Unique: gL577qKcMpaQEaDutDZZkw-1 X-Mimecast-MFC-AGG-ID: gL577qKcMpaQEaDutDZZkw_1756507351 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BDC9F19560AA; Fri, 29 Aug 2025 22:42:31 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 234BC1800280; Fri, 29 Aug 2025 22:42:26 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Asahi Lina , nouveau@lists.freedesktop.org (open list:DRM DRIVER FOR NVIDIA GPUS [RUST]) Subject: [PATCH v3 09/14] rust: gem: Introduce DriverObject::Args Date: Fri, 29 Aug 2025 18:35:24 -0400 Message-ID: <20250829224116.477990-10-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 This is an associated type that may be used in order to specify a data-type to pass to gem objects when construction them, allowing for drivers to more easily initialize their private-data for gem objects. Signed-off-by: Lyude Paul --- V3: * s/BaseDriverObject/DriverObject/ Signed-off-by: Lyude Paul --- drivers/gpu/drm/nova/gem.rs | 5 ++- rust/kernel/drm/gem/mod.rs | 75 +++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs index 10e3053f1a246..015cb56061a56 100644 --- a/drivers/gpu/drm/nova/gem.rs +++ b/drivers/gpu/drm/nova/gem.rs @@ -19,8 +19,9 @@ pub(crate) struct NovaObject {} impl gem::DriverObject for NovaObject { type Driver =3D NovaDriver; type Object =3D gem::Object; + type Args =3D (); =20 - fn new(_dev: &NovaDevice, _size: usize) -> impl PinInit { + fn new(_dev: &NovaDevice, _size: usize, _args: Self::Args) -> impl Pin= Init { try_pin_init!(NovaObject {}) } } @@ -34,7 +35,7 @@ pub(crate) fn new(dev: &NovaDevice, size: usize) -> Resul= t =3D drm::File<<::Driver as drm::= Driver>::File>; =20 +/// A helper macro for implementing AsRef> +macro_rules! impl_as_opaque { + ($type:ty where $tparam:ident : $tparam_trait:ident) =3D> { + impl core::convert::AsRef> for $type + where + D: kernel::drm::driver::Driver, + Self: kernel::drm::gem::DriverObject, + Self: kernel::drm::gem::IntoGEMObject, + $tparam: $tparam_trait, + { + fn as_ref(&self) -> &kernel::drm::gem::OpaqueObject { + // SAFETY: This cast is safe via our type invariant. + unsafe { &*((self.as_raw().cast_const()).cast()) } + } + } + }; +} + +pub(crate) use impl_as_opaque; + /// GEM object functions, which must be implemented by drivers. pub trait DriverObject: Sync + Send + Sized { /// Parent `Driver` for this object. @@ -29,8 +50,15 @@ pub trait DriverObject: Sync + Send + Sized { /// The GEM object type that will be passed to various callbacks. type Object: AllocImpl; =20 + /// The data type to use for passing arguments to [`BaseDriverObject::= new`]. + type Args; + /// Create a new driver data object for a GEM object of a given size. - fn new(dev: &drm::Device, size: usize) -> impl PinInit; + fn new( + dev: &drm::Device, + size: usize, + args: Self::Args, + ) -> impl PinInit; =20 /// Open a new handle to an existing object, associated with a File. fn open(_obj: &Self::Object, _file: &DriverFile) -> Result { @@ -42,7 +70,7 @@ fn close(_obj: &Self::Object, _file: &DriverFile) {} } =20 /// Trait that represents a GEM object subtype -pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted= { +pub trait IntoGEMObject: Sized + Sealed + AlwaysRefCounted { /// Returns a reference to the raw `drm_gem_object` structure, which m= ust be valid as long as /// this owning object is valid. fn as_raw(&self) -> *mut bindings::drm_gem_object; @@ -233,11 +261,11 @@ impl Object { }; =20 /// Create a new GEM object. - pub fn new(dev: &drm::Device, size: usize) -> Result> { + pub fn new(dev: &drm::Device, size: usize, args: T::Args) -= > Result> { let obj: Pin> =3D KBox::pin_init( try_pin_init!(Self { obj: Opaque::new(bindings::drm_gem_object::default()), - data <- T::new(dev, size), + data <- T::new(dev, size, args), // INVARIANT: The drm subsystem guarantees that the `struc= t drm_device` will live // as long as the GEM object lives. dev: dev.into(), @@ -289,7 +317,7 @@ extern "C" fn free_callback(obj: *mut bindings::drm_gem= _object) { } } =20 -impl super::private::Sealed for Object {} +impl Sealed for Object {} =20 impl Deref for Object { type Target =3D T; @@ -313,6 +341,39 @@ impl AllocImpl for Object { }; } =20 +impl_as_opaque!(Object where T: DriverObject); + +/// A GEM object whose private-data layout is not known. +/// +/// Not all GEM objects are created equal, and subsequently drivers may oc= casionally need to deal +/// with situations where they are working with a GEM object but have no k= nowledge of its +/// private-data layout. +/// +/// It may be used just like a normal [`Object`], with the exception that = it cannot access +/// driver-private data. +/// +/// # Invariant +/// +/// Via `#[repr(transparent)]`, this type is guaranteed to have an identic= al data layout to +/// `struct drm_gem_object`. +#[repr(transparent)] +pub struct OpaqueObject(Opaque, = PhantomData); + +impl IntoGEMObject for OpaqueObject { + unsafe fn from_raw<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a= Self { + // SAFETY: + // - This cast is safe via our type invariant. + // - `self_ptr` is guaranteed to be a valid pointer to a gem objec= t by our safety contract. + unsafe { &*self_ptr.cast::().cast_const() } + } + + fn as_raw(&self) -> *mut bindings::drm_gem_object { + self.0.get() + } +} + +impl Sealed for OpaqueObject {} + pub(super) const fn create_fops() -> bindings::file_operations { // SAFETY: As by the type invariant, it is safe to initialize `binding= s::file_operations` // zeroed. --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC42C2D1920 for ; Fri, 29 Aug 2025 22:42:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507373; cv=none; b=ZVaI40TCqVfUAozJRbp662vpcRN/zKm+8FwB50VRzEns4dMxX78FEEnt7tcK98l0OpO1VJkFZr4Aj8Q2aHuUGgFVHjovCGuIgp7TpcYhFtQl63OlHEjs2bPvGatFEIi5r5bEhSLy4bfXry0g8dDHj0ALsY5d6L3D6oZN8EmEYSs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507373; c=relaxed/simple; bh=bP83bRLNs6u3NXdRbmDA/+v97tpxjQ+7oGtQ5EU7VfM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uRMAA4pLy74ZmCyWMndOa20+yJrDhdwta+3syFjxWbIQ8OepnCeT36sophMiZ2dheYkHHMFeIl1KhNfFne6skpKjxlZlA1ena5omYB7dpf0pGVsYUbXwPbAhLrDupWDQkNv3IIA1TvPugU5QpdEVx6bRMarsLBAJ1TwFu+iq6xM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=MoPlVHyl; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MoPlVHyl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507370; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iziG5LYDK2S+G9DThM9w3Oo3gN9Xfc/1iYzxQcbBvf8=; b=MoPlVHylAjI8NC/G8VuYRfw+txgkVQ+/oW/rHIDvAMV/TuCk2OX7D/pxP629xwhmpP4ung DRrAShN7keD0bcdgaFVjeQswUTo7i1vpvkI5t9vK7I1A6iqUqQbo/NkKiCozhLN1ORvluZ drRUVBM2KKE0EN6Qjs0isIYsDIEAB1A= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-458-yBL4PIeMPVGjjPzRkDQuhQ-1; Fri, 29 Aug 2025 18:42:49 -0400 X-MC-Unique: yBL4PIeMPVGjjPzRkDQuhQ-1 X-Mimecast-MFC-AGG-ID: yBL4PIeMPVGjjPzRkDQuhQ_1756507366 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 82A7A1956095; Fri, 29 Aug 2025 22:42:45 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CD7D018003FC; Fri, 29 Aug 2025 22:42:39 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Asahi Lina , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Greg Kroah-Hartman , Asahi Lina , Viresh Kumar , Wedson Almeida Filho , Daniel Almeida , Alyssa Rosenzweig Subject: [PATCH v3 10/14] rust: drm: gem: shmem: Add DRM shmem helper abstraction Date: Fri, 29 Aug 2025 18:35:25 -0400 Message-ID: <20250829224116.477990-11-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 From: Asahi Lina The DRM shmem helper includes common code useful for drivers which allocate GEM objects as anonymous shmem. Add a Rust abstraction for this. Drivers can choose the raw GEM implementation or the shmem layer, depending on their needs. Signed-off-by: Asahi Lina Signed-off-by: Daniel Almeida Signed-off-by: Lyude Paul --- V2: * Use the drm_gem_shmem_init() and drm_gem_shmem_release() that I extracted so we can handle memory allocation in rust, which means we no longer have to handle freeing rust members of the struct by hand and have a closer implementation to the main gem object (this also gets rid of gem_create_object) * Get rid of GemObjectRef and UniqueGemObjectRef, we have ARef at home. * Use Device in Object * Cleanup Object::::new() a bit: * Cleanup safety comment * Use cast_mut() * Just import container_of!(), we use it all over anyhow * mut_shmem() -> as_shmem(), make it safe (there's no reason for being unsa= fe) * Remove any *const and *muts in structs, just use NonNull * Get rid of the previously hand-rolled sg_table bindings in shmem, use the bindings from Abdiel's sg_table patch series * Add a TODO at the top about DMA reservation APIs and a desire for WwMutex * Get rid of map_wc() and replace it with a new ObjectConfig struct. While it currently only specifies the map_wc flag, the idea here is that settings like map_wc() and parent_resv_obj() shouldn't be exposed as normal functions since the only place where it's safe to set them is when we're still guaranteed unique access to the GEM object, e.g. before returning it to the caller. Using a struct instead of individual arguments here is mainly because we'll be adding at least one more argument, and there's enough other gem shmem settings that trying to add all of them as individual function arguments in the future would be a bit messy. * Get rid of vm_numa_fields!, Lina didn't like this macro much either and I think that it's fine for us to just specify the #[cfg(=E2=80=A6)] attribu= tes by hand since we only need to do it twice. * Set drm_gem_object_funcs.vm_ops directly to drm_gem_shmem_vm_ops, don't export the various shmem funcs. I'm not sure why this wasn't possible before but it seems to work fine now. Signed-off-by: Lyude Paul --- rust/bindings/bindings_helper.h | 2 + rust/helpers/drm.c | 48 ++++- rust/kernel/drm/gem/mod.rs | 3 +- rust/kernel/drm/gem/shmem.rs | 311 ++++++++++++++++++++++++++++++++ 4 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 rust/kernel/drm/gem/shmem.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 00fe0449ed6de..e8386e3772376 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/drm.c b/rust/helpers/drm.c index 450b406c6f273..a4e997d0b4732 100644 --- a/rust/helpers/drm.c +++ b/rust/helpers/drm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 =20 #include +#include #include =20 #ifdef CONFIG_DRM @@ -20,4 +21,49 @@ __u64 rust_helper_drm_vma_node_offset_addr(struct drm_vm= a_offset_node *node) return drm_vma_node_offset_addr(node); } =20 -#endif +#ifdef CONFIG_DRM_GEM_SHMEM_HELPER +void rust_helper_drm_gem_shmem_object_free(struct drm_gem_object *obj) +{ + return drm_gem_shmem_object_free(obj); +} + +void rust_helper_drm_gem_shmem_object_print_info(struct drm_printer *p, un= signed int indent, + const struct drm_gem_obj= ect *obj) +{ + drm_gem_shmem_object_print_info(p, indent, obj); +} + +int rust_helper_drm_gem_shmem_object_pin(struct drm_gem_object *obj) +{ + return drm_gem_shmem_object_pin(obj); +} + +void rust_helper_drm_gem_shmem_object_unpin(struct drm_gem_object *obj) +{ + drm_gem_shmem_object_unpin(obj); +} + +struct sg_table *rust_helper_drm_gem_shmem_object_get_sg_table(struct drm_= gem_object *obj) +{ + return drm_gem_shmem_object_get_sg_table(obj); +} + +int rust_helper_drm_gem_shmem_object_vmap(struct drm_gem_object *obj, + struct iosys_map *map) +{ + return drm_gem_shmem_object_vmap(obj, map); +} + +void rust_helper_drm_gem_shmem_object_vunmap(struct drm_gem_object *obj, + struct iosys_map *map) +{ + drm_gem_shmem_object_vunmap(obj, map); +} + +int rust_helper_drm_gem_shmem_object_mmap(struct drm_gem_object *obj, stru= ct vm_area_struct *vma) +{ + return drm_gem_shmem_object_mmap(obj, vma); +} + +#endif /* CONFIG_DRM_GEM_SHMEM_HELPER */ +#endif /* CONFIG_DRM */ diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index fe6ff3762a504..f9f9727f14e4a 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -3,6 +3,8 @@ //! DRM GEM API //! //! C header: [`include/linux/drm/drm_gem.h`](srctree/include/linux/drm/dr= m_gem.h) +#[cfg(CONFIG_DRM_GEM_SHMEM_HELPER =3D "y")] +pub mod shmem; =20 use crate::{ alloc::flags::*, @@ -215,7 +217,6 @@ fn create_mmap_offset(&self) -> Result { impl BaseObject for T {} =20 /// Crate-private base operations shared by all GEM object classes. -#[expect(unused)] pub(crate) trait BaseObjectPrivate: IntoGEMObject { /// Return a pointer to this object's dma_resv. fn raw_dma_resv(&self) -> *mut bindings::dma_resv { diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs new file mode 100644 index 0000000000000..6a8a392c3691b --- /dev/null +++ b/rust/kernel/drm/gem/shmem.rs @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! DRM GEM shmem helper objects +//! +//! C header: [`include/linux/drm/drm_gem_shmem_helper.h`](srctree/include= /linux/drm/drm_gem_shmem_helper.h) + +// TODO: +// - There are a number of spots here that manually acquire/release the DM= A reservation lock using +// dma_resv_(un)lock(). In the future we should add support for ww mutex= , expose a method to +// acquire a reference to the WwMutex, and then use that directly instea= d of the C functions here. + +use crate::{ + container_of, + drm::{device, driver, gem, private::Sealed}, + error::{from_err_ptr, to_result}, + prelude::*, + scatterlist, + types::{ARef, Opaque}, +}; +use core::{ + mem::MaybeUninit, + ops::{Deref, DerefMut}, + ptr::{addr_of_mut, NonNull}, + slice, +}; +use gem::{BaseObject, BaseObjectPrivate, DriverObject, IntoGEMObject, Opaq= ueObject}; + +/// A struct for controlling the creation of shmem-backed GEM objects. +/// +/// This is used with [`Object::new()`] to control various properties that= can only be set when +/// initially creating a shmem-backed GEM object. +#[derive(Default)] +pub struct ObjectConfig<'a, T: DriverObject> { + /// Whether to set the write-combine map flag. + pub map_wc: bool, + + /// Reuse the DMA reservation from another GEM object. + /// + /// The newly created [`Object`] will hold an owned refcount to `paren= t_resv_obj` if specified. + pub parent_resv_obj: Option<&'a OpaqueObject>, +} + +/// A shmem-backed GEM object. +/// +/// # Invariants +/// +/// The DRM core ensures that `dev` will remain valid for as long as the o= bject. +#[repr(C)] +#[pin_data] +pub struct Object { + #[pin] + obj: Opaque, + dev: NonNull>, + // Parent object that owns this object's DMA reservation object + parent_resv_obj: Option>>, + #[pin] + inner: T, +} + +super::impl_as_opaque!(Object where T: DriverObject); + +impl Object { + /// `drm_gem_object_funcs` vtable suitable for GEM shmem objects. + const VTABLE: bindings::drm_gem_object_funcs =3D bindings::drm_gem_obj= ect_funcs { + free: Some(Self::free_callback), + open: Some(super::open_callback::), + close: Some(super::close_callback::), + print_info: Some(bindings::drm_gem_shmem_object_print_info), + export: None, + pin: Some(bindings::drm_gem_shmem_object_pin), + unpin: Some(bindings::drm_gem_shmem_object_unpin), + get_sg_table: Some(bindings::drm_gem_shmem_object_get_sg_table), + vmap: Some(bindings::drm_gem_shmem_object_vmap), + vunmap: Some(bindings::drm_gem_shmem_object_vunmap), + mmap: Some(bindings::drm_gem_shmem_object_mmap), + status: None, + rss: None, + // SAFETY: `drm_gem_shmem_vm_ops` is static const on the C side, s= o immutable references are + // safe here and such references shall be valid forever + vm_ops: unsafe { &bindings::drm_gem_shmem_vm_ops }, + evict: None, + }; + + /// Return a raw pointer to the embedded drm_gem_shmem_object. + fn as_shmem(&self) -> *mut bindings::drm_gem_shmem_object { + self.obj.get() + } + + /// Create a new shmem-backed DRM object of the given size. + /// + /// Additional config options can be specified using `config`. + pub fn new( + dev: &device::Device, + size: usize, + config: ObjectConfig<'_, T>, + args: T::Args, + ) -> Result> { + let new: Pin> =3D KBox::try_pin_init( + try_pin_init!(Self { + obj <- Opaque::init_zeroed(), + dev: NonNull::from(dev), + parent_resv_obj: config.parent_resv_obj.map(|p| p.into()), + inner <- T::new(dev, size, args), + }), + GFP_KERNEL, + )?; + + // SAFETY: `obj.as_raw()` is guaranteed to be valid by the initial= ization above. + unsafe { (*new.as_raw()).funcs =3D &Self::VTABLE }; + + // SAFETY: The arguments are all valid via the type invariants. + to_result(unsafe { bindings::drm_gem_shmem_init(dev.as_raw(), new.= as_shmem(), size) })?; + + // SAFETY: We never move out of `self`. + let new =3D KBox::into_raw(unsafe { Pin::into_inner_unchecked(new)= }); + + // SAFETY: We're taking over the owned refcount from `drm_gem_shme= m_init`. + let obj =3D unsafe { ARef::from_raw(NonNull::new_unchecked(new)) }; + + // Start filling out values from `config` + if let Some(parent_resv) =3D config.parent_resv_obj { + // SAFETY: We have yet to expose the new gem object outside of= this function, so it is + // safe to modify this field. + unsafe { (*obj.obj.get()).base.resv =3D parent_resv.raw_dma_re= sv() }; + } + + // SAFETY: We have yet to expose this object outside of this funct= ion, so we're guaranteed + // to have exclusive access - thus making this safe to hold a muta= ble reference to. + let shmem =3D unsafe { &mut *obj.as_shmem() }; + shmem.set_map_wc(config.map_wc); + + Ok(obj) + } + + /// Returns the `Device` that owns this GEM object. + pub fn dev(&self) -> &device::Device { + // SAFETY: We are guaranteed that `dev` is valid for as long as th= is object is valid by our + // type invariants + unsafe { self.dev.as_ref() } + } + + extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) { + // SAFETY: + // - DRM always passes a valid gem object here + // - We used drm_gem_shmem_create() in our create_gem_object callb= ack, so we know that + // `obj` is contained within a drm_gem_shmem_object + let this =3D unsafe { container_of!(obj, bindings::drm_gem_shmem_o= bject, base) }; + + // SAFETY: + // - We're in free_callback - so this function is safe to call. + // - We won't be using the gem resources on `this` after this call. + unsafe { bindings::drm_gem_shmem_release(this) }; + + // SAFETY: + // - We verified above that `obj` is valid, which makes `this` val= id + // - This function is set in AllocOps, so we know that `this` is c= ontained within a + // `Object` + let this =3D unsafe { container_of!(this.cast::>(), Self= , obj) }; + + // SAFETY: We're recovering the Kbox<> we created in gem_create_ob= ject() + let _ =3D unsafe { KBox::from_raw(this) }; + } + + /// Creates (if necessary) and returns an immutable reference to a sca= tter-gather table of DMA + /// pages for this object. + /// + /// This will pin the object in memory. + #[inline] + pub fn sg_table(&self) -> Result<&scatterlist::SGTable> { + // SAFETY: + // - drm_gem_shmem_get_pages_sgt is thread-safe. + // - drm_gem_shmem_get_pages_sgt returns either a valid pointer to= a scatterlist, or an + // error pointer. + let sgt =3D from_err_ptr(unsafe { bindings::drm_gem_shmem_get_page= s_sgt(self.as_shmem()) })?; + + // SAFETY: We checked above that `sgt` is not an error pointer, so= it must be a valid + // pointer to a scatterlist + Ok(unsafe { scatterlist::SGTable::from_raw(sgt) }) + } + + /// Creates and returns a virtual kernel memory mapping for this objec= t. + pub fn vmap(&self) -> Result> { + let mut map: MaybeUninit =3D MaybeUninit::uni= nit(); + + // SAFETY: + // - drm_gem_shmem_vmap can be called with the DMA reservation loc= k held + // - Our ARef is proof that `obj` is safe to deref + to_result(unsafe { + // TODO: see top of file + bindings::dma_resv_lock(self.raw_dma_resv(), core::ptr::null_m= ut()); + let ret =3D bindings::drm_gem_shmem_vmap_locked(self.as_shmem(= ), map.as_mut_ptr()); + bindings::dma_resv_unlock(self.raw_dma_resv()); + ret + })?; + + // SAFETY: if drm_gem_shmem_vmap did not fail, map is initialized = now + let map =3D unsafe { map.assume_init() }; + + Ok(VMap { + map, + owner: self.into(), + }) + } +} + +impl Deref for Object { + type Target =3D T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for Object { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl Sealed for Object {} + +impl gem::IntoGEMObject for Object { + fn as_raw(&self) -> *mut bindings::drm_gem_object { + // SAFETY: Our immutable reference is proof that this is afe to de= reference + unsafe { addr_of_mut!((*self.obj.get()).base) } + } + + unsafe fn from_raw<'a>(obj: *mut bindings::drm_gem_object) -> &'a Obje= ct { + // SAFETY: The safety contract of from_gem_obj() guarantees that `= obj` is contained within + // `Self` + unsafe { + let obj: *mut Opaque<_> =3D + container_of!(obj, bindings::drm_gem_shmem_object, base).c= ast(); + + &*container_of!(obj, Object, obj) + } + } +} + +impl driver::AllocImpl for Object { + type Driver =3D T::Driver; + + const ALLOC_OPS: driver::AllocOps =3D driver::AllocOps { + gem_create_object: None, + prime_handle_to_fd: None, + prime_fd_to_handle: None, + gem_prime_import: None, + gem_prime_import_sg_table: Some(bindings::drm_gem_shmem_prime_impo= rt_sg_table), + dumb_create: Some(bindings::drm_gem_shmem_dumb_create), + dumb_map_offset: None, + }; +} + +/// A virtual mapping for a shmem-backed GEM object in kernel address spac= e. +pub struct VMap { + map: bindings::iosys_map, + owner: ARef>, +} + +impl VMap { + /// Returns a const raw pointer to the start of the mapping. + pub fn as_ptr(&self) -> *const core::ffi::c_void { + // SAFETY: The shmem helpers always return non-iomem maps + unsafe { self.map.__bindgen_anon_1.vaddr } + } + + /// Returns a mutable raw pointer to the start of the mapping. + pub fn as_mut_ptr(&mut self) -> *mut core::ffi::c_void { + // SAFETY: The shmem helpers always return non-iomem maps + unsafe { self.map.__bindgen_anon_1.vaddr } + } + + /// Returns a byte slice view of the mapping. + pub fn as_slice(&self) -> &[u8] { + // SAFETY: The vmap maps valid memory up to the owner size + unsafe { slice::from_raw_parts(self.as_ptr().cast(), self.owner.si= ze()) } + } + + /// Returns mutable a byte slice view of the mapping. + pub fn as_mut_slice(&mut self) -> &mut [u8] { + // SAFETY: The vmap maps valid memory up to the owner size + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().cast(), self.= owner.size()) } + } + + /// Borrows a reference to the object that owns this virtual mapping. + pub fn owner(&self) -> &Object { + &self.owner + } +} + +impl Drop for VMap { + fn drop(&mut self) { + // SAFETY: + // - This function is safe to call with the DMA reservation lock h= eld + // - Our `ARef` is proof that the underlying gem object here is in= itialized and thus safe to + // dereference. + unsafe { + let resv =3D self.owner.raw_dma_resv(); + + // TODO: see top of file + bindings::dma_resv_lock(resv, core::ptr::null_mut()); + bindings::drm_gem_shmem_vunmap_locked(self.owner.as_shmem(), &= mut self.map); + bindings::dma_resv_unlock(resv); + } + } +} + +/// SAFETY: `iosys_map` objects are safe to send across threads. +unsafe impl Send for VMap {} +/// SAFETY: `iosys_map` objects are safe to send across threads. +unsafe impl Sync for VMap {} --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61F492D9EE0 for ; Fri, 29 Aug 2025 22:43:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507384; cv=none; b=JFDFFjpicJjdDFRmfKYJg+FDoUah0gJR4zZ1vbsbMdICfOMTJwCufAcv9ax0MpYaPdE0shHhRJz6F/h78OfKTfp3LycVRg1Nc9uDlMNtOOWE3qPd2pIx3iFnWLzQI+CSsNBCI3bKjhuoADWn/kugPh5hvQPEcOB2UN7l7zQicBA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507384; c=relaxed/simple; bh=J4kt0AH42ZTONC28Th1Okh8r1ILQmR1UJzSCMd6Q6e8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DgEODfPryAMoBXdeeoIrVygGPK25c/3Z+ANmQXHqvUPoitEaM9jm0jGCPxzcDR1Uhl8nx+OV+M+29XOcvO3O9EwgjeoToxH6k3ja8/YUjb95Fsb40al2NMR0iobS3gNA2GL6sW5YgnI+jCYygQTh7U3EEthS2U637Si/18H8DE0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ZGCpEY7/; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ZGCpEY7/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507380; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ze5i6Pi0AsJ8OZnGY1zOw/cDXaH5xQ4ENMo0wMvIxrk=; b=ZGCpEY7/5rzCYb6s6CWtJdTb/Yt5e8fCFDa0Huw/gVBm2mYrBoSueFci4pnpkLX7KgF0u1 t3izcTaeWqVbHtW3DGTTMsnOZXfCMiUSzCvsRQC6PMUTQHhQjAruMSkcLPxIgh6THV7909 508APAwhRDRyhlZShmhPDPQ21sWOEaY= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-275-I9enlBaGM4CVqSLLlPdsZg-1; Fri, 29 Aug 2025 18:42:57 -0400 X-MC-Unique: I9enlBaGM4CVqSLLlPdsZg-1 X-Mimecast-MFC-AGG-ID: I9enlBaGM4CVqSLLlPdsZg_1756507373 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 4D75719560AD; Fri, 29 Aug 2025 22:42:53 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E951E18003FC; Fri, 29 Aug 2025 22:42:48 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Daniel Almeida , Asahi Lina Subject: [PATCH v3 11/14] rust: drm: gem: Introduce SGTableRef Date: Fri, 29 Aug 2025 18:35:26 -0400 Message-ID: <20250829224116.477990-12-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Currently we expose the ability to retrieve an SGTable for an shmem gem object using gem::shmem::Object::::sg_table(). However, this only gives = us a borrowed reference. This being said - retrieving an SGTable is a fallible operation, and as such it's reasonable that a driver may want to hold onto an SGTable for longer then a reference would allow in order to avoid having to deal with fallibility every time they want to access the SGTable. One such driver with this usecase is the Asahi driver. So to support this, let's introduce SGTableRef - which both holds a pointer to the SGTable and a reference to its respective GEM object in order to keep the GEM object alive for as long as the SGTableRef. The type can be used identically to a normal SGTable. Signed-off-by: Lyude Paul --- V3: * Rename OwnedSGTable to SGTableRef. Since the current version of the SGTable abstractions now has a `Owned` and `Borrowed` variant, I think renaming this to SGTableRef makes things less confusing. We do however, keep the name of owned_sg_table() as-is. Signed-off-by: Lyude Paul --- rust/kernel/drm/gem/shmem.rs | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index 6a8a392c3691b..1437cda27a22c 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -178,6 +178,22 @@ pub fn sg_table(&self) -> Result<&scatterlist::SGTable= > { Ok(unsafe { scatterlist::SGTable::from_raw(sgt) }) } =20 + /// Creates (if necessary) and returns an owned reference to a scatter= -gather table of DMA pages + /// for this object. + /// + /// This is the same as [`sg_table`](Self::sg_table), except that it i= nstead returns a + /// [`OwnedSGTable`] which holds a reference to the associated gem obj= ect. + /// + /// This will pin the object in memory. + pub fn owned_sg_table(&self) -> Result> { + Ok(SGTableRef { + sgt: self.sg_table()?.into(), + // INVARIANT: We take an owned refcount to `self` here, ensuri= ng that `sgt` remains + // valid for as long as this `OwnedSGTable`. + _owner: self.into(), + }) + } + /// Creates and returns a virtual kernel memory mapping for this objec= t. pub fn vmap(&self) -> Result> { let mut map: MaybeUninit =3D MaybeUninit::uni= nit(); @@ -309,3 +325,37 @@ fn drop(&mut self) { unsafe impl Send for VMap {} /// SAFETY: `iosys_map` objects are safe to send across threads. unsafe impl Sync for VMap {} + +/// An owned reference to a scatter-gather table of DMA address spans for = a GEM shmem object. +/// +/// This object holds an owned reference to the underlying GEM shmem objec= t, ensuring that the +/// [`SGTable`] referenced by `SGTableRef` remains valid for the lifetime = of this object. +/// +/// # Invariants +/// +/// - `sgt` is kept alive by `_owner`, ensuring it remains valid for as lo= ng as `Self`. +/// - `sgt` corresponds to the owned object in `_owner`. +/// - This object is only exposed in situations where we know the underlyi= ng `SGTable` will not be +/// modified for the lifetime of this object. +/// +/// [`SGTable`]: scatterlist::SGTable +pub struct SGTableRef { + sgt: NonNull, + _owner: ARef>, +} + +// SAFETY: This object is only exposed in situations where we know the und= erlying `SGTable` will not +// be modified for the lifetime of this object. +unsafe impl Send for SGTableRef {} +// SAFETY: This object is only exposed in situations where we know the und= erlying `SGTable` will not +// be modified for the lifetime of this object. +unsafe impl Sync for SGTableRef {} + +impl Deref for SGTableRef { + type Target =3D scatterlist::SGTable; + + fn deref(&self) -> &Self::Target { + // SAFETY: Creating an immutable reference to this is safe via our= type invariants. + unsafe { self.sgt.as_ref() } + } +} --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CAB072D879B for ; Fri, 29 Aug 2025 22:43:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507389; cv=none; b=BIawNnr3p/A9ya9bDZzoHMcM3G6XfsspR865LNqW2/0xTEHa7T6/G3ZcQ/mUeTVfETxD0pFjhxD72lNoWuShTXV8mX4FfR5h+9XsCIgyFJjS4UqprigKnDdapPaGqyuZTDsiHE3UnGtFl57ukxW794aprUsfd3B75t7No2wfenE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507389; c=relaxed/simple; bh=TAHkk+DHc4JvZqTuooUCu7rvxP0alLpYlxkiJmeOPBo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=a0sU643k963GvzxZQ1ShnpcDhfrUZMs67j/KX9Tg/BpL9cmfocqkrj7AG6GcLs3Ae2hyx3K9zn8JpnnKHHaYUWP0Kv+D7D1YaMkiSDRP2F8cqqMpNNZDgH8yteYFPgyYjva0k7xmAUnSYOt56dQNPgvPpoq9CX3u71UyFz8XUws= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=MZKY2ooG; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="MZKY2ooG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507386; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=S2F8pTf5YP3aNkFLN54qB5DgCyFojIIWqrlzr2JxhFU=; b=MZKY2ooGq7htjcpX93eXd9gCN1sEAIHMxuPSMMCE8gRx67x1hGSn3fPsNj0pfiIfWRMVq0 oxvD+OxwWtNdbpYFvmAgPzSirmBTQtXSkV4YZbmpgaQkn3h+9TW6G6icRu+jn3HkcqZQUo x4HHXT9TB6DV1XeIU7iFdgPDGkQ3qf4= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-396-sNZ_ShMXOKG6hwSDIMw1iQ-1; Fri, 29 Aug 2025 18:43:03 -0400 X-MC-Unique: sNZ_ShMXOKG6hwSDIMw1iQ-1 X-Mimecast-MFC-AGG-ID: sNZ_ShMXOKG6hwSDIMw1iQ_1756507381 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D1D6E195604F; Fri, 29 Aug 2025 22:43:00 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DFF3E1800280; Fri, 29 Aug 2025 22:42:55 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , Greg Kroah-Hartman , Wedson Almeida Filho , Viresh Kumar , Tamir Duberstein , Xiangfei Ding , linux-media@vger.kernel.org (open list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b), linaro-mm-sig@lists.linaro.org (moderated list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b) Subject: [PATCH v3 12/14] rust: Add dma_buf stub bindings Date: Fri, 29 Aug 2025 18:35:27 -0400 Message-ID: <20250829224116.477990-13-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" In order to implement the gem export callback, we need a type to represent struct dma_buf. So - this commit introduces a set of stub bindings for dma_buf. These bindings provide a ref-counted DmaBuf object, but don't currently implement any functionality for using the DmaBuf. Signed-off-by: Lyude Paul Reviewed-by: Daniel Almeida --- V3: * Rename as_ref() to from_raw() Signed-off-by: Lyude Paul --- rust/kernel/dma_buf.rs | 40 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 2 files changed, 41 insertions(+) create mode 100644 rust/kernel/dma_buf.rs diff --git a/rust/kernel/dma_buf.rs b/rust/kernel/dma_buf.rs new file mode 100644 index 0000000000000..a66829afcd129 --- /dev/null +++ b/rust/kernel/dma_buf.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! DMA buffer API +//! +//! C header: [`include/linux/dma-buf.h`](srctree/include/linux/dma-buf.h) + +use bindings; +use kernel::types::*; + +/// A DMA buffer object. +/// +/// # Invariants +/// +/// The data layout of this type is equivalent to that of `struct dma_buf`. +#[repr(transparent)] +pub struct DmaBuf(Opaque); + +// SAFETY: `struct dma_buf` is thread-safe +unsafe impl Send for DmaBuf {} +// SAFETY: `struct dma_buf` is thread-safe +unsafe impl Sync for DmaBuf {} + +#[expect(unused)] +impl DmaBuf { + /// Convert from a `*mut bindings::dma_buf` to a [`DmaBuf`]. + /// + /// # Safety + /// + /// The caller guarantees that `self_ptr` points to a valid initialize= d `struct dma_buf` for the + /// duration of the lifetime of `'a`, and promises to not violate rust= 's data aliasing rules + /// using the reference provided by this function. + pub(crate) unsafe fn from_raw<'a>(self_ptr: *mut bindings::dma_buf) ->= &'a Self { + // SAFETY: Our data layout is equivalent to `dma_buf` . + unsafe { &*self_ptr.cast() } + } + + pub(crate) fn as_raw(&self) -> *mut bindings::dma_buf { + self.0.get() + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index fcffc3988a903..59242d83efe21 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -81,6 +81,7 @@ pub mod device_id; pub mod devres; pub mod dma; +pub mod dma_buf; pub mod driver; #[cfg(CONFIG_DRM =3D "y")] pub mod drm; --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECCA62DA757 for ; Fri, 29 Aug 2025 22:43:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507400; cv=none; b=eFKMTwyX0O98XxkVx0M9TR15234P14EsbynRpMFGXldrK5bdck4tU/SYrvp2AuiysCMo91obGsgwo9t3aYwO+HYcKHhxhtIj2SJ4IqH1pQDhaPoiP3Pwdbbum8k/gTajWgj3S/KwlmKZDSkgsDQhnPVVH3G88hVbB4wnqkt53Bw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507400; c=relaxed/simple; bh=N8kxUBPd55YKdu/xSoioFdUgZRLBsIqnkmLbhSBJ8zI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XDG10mxIJ5aEti+BQtFXxEPWs4VE5Wht1v0wlfzlcziq18naTNQrwhh1jZnsPk7ITUniPZlYA15QWsPf2ysNAI0bRPZnc9mN5ToUBmlDCWh7PUT8oimviqSpuFJMJj9x5KSQJXIrd1uy1vWPytjQ/l5l8PztDZv6tKu5a4J507E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=J6b09Qd7; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="J6b09Qd7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507397; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8eKMZA2jSOMS+3g9kP9wxgZR4GNqJmM76RSX3YLcOg0=; b=J6b09Qd7JGURrQEQsAoWZamfeZSy5MvRD0AliYL/a+uH04GXziGBCh7kGre2CBSfa9QcPp NL1ZM80YeFkg5OW0hHiCTaS/9Yvuv6YRNN6F9ZWp1WF8frk2JC6i7fHATl7uxGmoc2ltf2 zg/DyvpRKRhUmicjsF6GSukCywQDOpc= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-251-cwbB1E0PNcKyrTfAt0tiVQ-1; Fri, 29 Aug 2025 18:43:16 -0400 X-MC-Unique: cwbB1E0PNcKyrTfAt0tiVQ-1 X-Mimecast-MFC-AGG-ID: cwbB1E0PNcKyrTfAt0tiVQ_1756507393 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0BF75195E914; Fri, 29 Aug 2025 22:43:13 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2C6BC1800280; Fri, 29 Aug 2025 22:43:06 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , Daniel Almeida , Asahi Lina , nouveau@lists.freedesktop.org (open list:DRM DRIVER FOR NVIDIA GPUS [RUST]), linux-media@vger.kernel.org (open list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b), linaro-mm-sig@lists.linaro.org (moderated list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b) Subject: [PATCH v3 13/14] rust: drm: gem: Add export() callback Date: Fri, 29 Aug 2025 18:35:28 -0400 Message-ID: <20250829224116.477990-14-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" This introduces an optional export() callback for GEM objects, which is used to implement the drm_gem_object_funcs->export function. Signed-off-by: Lyude Paul --- drivers/gpu/drm/nova/gem.rs | 1 + rust/kernel/drm/gem/mod.rs | 72 +++++++++++++++++++++++++++++++++++- rust/kernel/drm/gem/shmem.rs | 6 ++- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs index 015cb56061a56..bbce6b0f4e6a4 100644 --- a/drivers/gpu/drm/nova/gem.rs +++ b/drivers/gpu/drm/nova/gem.rs @@ -16,6 +16,7 @@ #[pin_data] pub(crate) struct NovaObject {} =20 +#[vtable] impl gem::DriverObject for NovaObject { type Driver =3D NovaDriver; type Object =3D gem::Object; diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index f9f9727f14e4a..1ac25fc6d527b 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -8,7 +8,7 @@ =20 use crate::{ alloc::flags::*, - bindings, + bindings, dma_buf, drm::driver::{AllocImpl, AllocOps}, drm::{self, private::Sealed}, error::{to_result, Result}, @@ -45,6 +45,7 @@ fn as_ref(&self) -> &kernel::drm::gem::OpaqueObject { pub(crate) use impl_as_opaque; =20 /// GEM object functions, which must be implemented by drivers. +#[vtable] pub trait DriverObject: Sync + Send + Sized { /// Parent `Driver` for this object. type Driver: drm::Driver; @@ -69,6 +70,11 @@ fn open(_obj: &Self::Object, _file: &DriverFile) -= > Result { =20 /// Close a handle to an existing object, associated with a File. fn close(_obj: &Self::Object, _file: &DriverFile) {} + + /// Optional handle for exporting a gem object. + fn export(_obj: &Self::Object, _flags: u32) -> Result> { + unimplemented!() + } } =20 /// Trait that represents a GEM object subtype @@ -138,6 +144,21 @@ extern "C" fn close_callback( T::close(obj, file); } =20 +extern "C" fn export_callback( + raw_obj: *mut bindings::drm_gem_object, + flags: i32, +) -> *mut bindings::dma_buf { + // SAFETY: `export_callback` is specified in the AllocOps structure fo= r `Object`, ensuring + // that `raw_obj` is contained within a `Object`. + let obj =3D unsafe { T::Object::from_raw(raw_obj) }; + + match T::export(obj, flags as u32) { + // DRM takes a hold of the reference + Ok(buf) =3D> buf.into_raw(), + Err(e) =3D> e.to_ptr(), + } +} + impl IntoGEMObject for Object { fn as_raw(&self) -> *mut bindings::drm_gem_object { self.obj.get() @@ -248,7 +269,11 @@ impl Object { open: Some(open_callback::), close: Some(close_callback::), print_info: None, - export: None, + export: if T::HAS_EXPORT { + Some(export_callback::) + } else { + None + }, pin: None, unpin: None, get_sg_table: None, @@ -375,6 +400,49 @@ fn as_raw(&self) -> *mut bindings::drm_gem_object { =20 impl Sealed for OpaqueObject {} =20 +/// A [`dma_buf::DmaBuf`] which has been exported from a GEM object. +/// +/// The [`dma_buf::DmaBuf`] will be released when this type is dropped. +/// +/// # Invariants +/// +/// - `self.0` points to a valid initialized [`dma_buf::DmaBuf`] for the l= ifetime of this object. +/// - The GEM object from which this [`dma_buf::DmaBuf`] was exported from= is guaranteed to be of +/// type `T`. +pub struct DmaBuf(NonNull, PhantomData<= T>); + +impl Deref for DmaBuf { + type Target =3D dma_buf::DmaBuf; + + #[inline] + fn deref(&self) -> &Self::Target { + // SAFETY: This pointer is guaranteed to be valid by our type inva= riants. + unsafe { self.0.as_ref() } + } +} + +impl Drop for DmaBuf { + #[inline] + fn drop(&mut self) { + // SAFETY: + // - `dma_buf::DmaBuf` is guaranteed to have an identical layout t= o `struct dma_buf` + // by its type invariants. + // - We hold the last reference to this `DmaBuf`, making it safe t= o destroy. + unsafe { bindings::drm_gem_dmabuf_release(self.0.cast().as_ptr()) } + } +} + +impl DmaBuf { + /// Leak the reference for this [`DmaBuf`] and return a raw pointer to= it. + #[inline] + pub(crate) fn into_raw(self) -> *mut bindings::dma_buf { + let dma_ptr =3D self.as_raw(); + + core::mem::forget(self); + dma_ptr + } +} + pub(super) const fn create_fops() -> bindings::file_operations { // SAFETY: As by the type invariant, it is safe to initialize `binding= s::file_operations` // zeroed. diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs index 1437cda27a22c..b3a70e6001842 100644 --- a/rust/kernel/drm/gem/shmem.rs +++ b/rust/kernel/drm/gem/shmem.rs @@ -66,7 +66,11 @@ impl Object { open: Some(super::open_callback::), close: Some(super::close_callback::), print_info: Some(bindings::drm_gem_shmem_object_print_info), - export: None, + export: if T::HAS_EXPORT { + Some(super::export_callback::) + } else { + None + }, pin: Some(bindings::drm_gem_shmem_object_pin), unpin: Some(bindings::drm_gem_shmem_object_unpin), get_sg_table: Some(bindings::drm_gem_shmem_object_get_sg_table), --=20 2.50.0 From nobody Fri Oct 3 13:23:46 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1248A2D8383 for ; Fri, 29 Aug 2025 22:43:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507412; cv=none; b=TKCg+pAPtvd1N35cBRtlSSAZADNqke2c0Hp/oCGFN/vDeVd60N/MA5TxK3nDqasRUWDwOG2ej/2M4AECdiZnUQBF9D4wcW5zb2NEJBnnZDWow4e+GoYhU/Nvi7R741S/e8m3gANoY2vKEsHz1cTRYahhi6oAy8xCAsIqTiCV4n8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756507412; c=relaxed/simple; bh=v7GAqsPgMWB93HEjuq9XkbeHGGs3gLpuJrD8ZVFOITc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qt7a57+9wNxiaY1cUqtUquETjBXdgJN9dOyJSQRQANWs6IovdwFVVYZVURDkTRlLwjSqbb2JHA7TfPLvyN0VPoGhN33Diz2BLAPG4vL/k2JfBwXAWHQCxpdLN2y6ngRElJT09XIidhn+XXStAFG3r9Ubw5WTgM8uhSzb3qYMRco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=TY0MnBzq; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="TY0MnBzq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756507409; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=C/CGc5IYCcldED/cw1fL3e87GMHcob6lNDfrF2dVSZ4=; b=TY0MnBzqbv3gYk5hceKsvfzLZzCzKW+uF2MeIoRluplAA7YfG+B854T7z737l9P+0JRoKo bG+7tKcvxM8nw1IC0kDTJ9dpvcBmfeeMB44ysg8pWQpa5bpEXLs+C+QdotiOGe05ZlpukJ gOKK0nHmNae0VqHZSureMunyOC5WWcY= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-583-_Ln9jEUpPEmpud-bgdS2Tg-1; Fri, 29 Aug 2025 18:43:25 -0400 X-MC-Unique: _Ln9jEUpPEmpud-bgdS2Tg-1 X-Mimecast-MFC-AGG-ID: _Ln9jEUpPEmpud-bgdS2Tg_1756507402 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8A32E1956048; Fri, 29 Aug 2025 22:43:22 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.80.78]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 998A2180028A; Fri, 29 Aug 2025 22:43:17 +0000 (UTC) From: Lyude Paul To: dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , Daniel Almeida , Asahi Lina , linux-media@vger.kernel.org (open list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b), linaro-mm-sig@lists.linaro.org (moderated list:DMA BUFFER SHARING FRAMEWORK:Keyword:\bdma_(?:buf|fence|resv)\b) Subject: [PATCH v3 14/14] rust: drm: gem: Add BaseObject::prime_export() Date: Fri, 29 Aug 2025 18:35:29 -0400 Message-ID: <20250829224116.477990-15-lyude@redhat.com> In-Reply-To: <20250829224116.477990-1-lyude@redhat.com> References: <20250829224116.477990-1-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" We just added an export() callback that GEM objects can implement, but without any way of actually exporting a DmaBuf. So let's add one by introducing bindings for drm_gem_prime_export(). Signed-off-by: Lyude Paul Reviewed-by: Daniel Almeida --- rust/kernel/dma_buf.rs | 1 - rust/kernel/drm/gem/mod.rs | 24 +++++++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/rust/kernel/dma_buf.rs b/rust/kernel/dma_buf.rs index a66829afcd129..a2086918efd17 100644 --- a/rust/kernel/dma_buf.rs +++ b/rust/kernel/dma_buf.rs @@ -20,7 +20,6 @@ unsafe impl Send for DmaBuf {} // SAFETY: `struct dma_buf` is thread-safe unsafe impl Sync for DmaBuf {} =20 -#[expect(unused)] impl DmaBuf { /// Convert from a `*mut bindings::dma_buf` to a [`DmaBuf`]. /// diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index 1ac25fc6d527b..75ffd5541e84c 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -11,7 +11,7 @@ bindings, dma_buf, drm::driver::{AllocImpl, AllocOps}, drm::{self, private::Sealed}, - error::{to_result, Result}, + error::{from_err_ptr, to_result, Result}, prelude::*, types::{ARef, AlwaysRefCounted, Opaque}, }; @@ -225,6 +225,28 @@ fn lookup_handle(file: &drm::File, handle:= u32) -> Result Ok(unsafe { ARef::from_raw(obj.into()) }) } =20 + /// Export a [`DmaBuf`] for this GEM object using the DRM prime helper= library. + /// + /// `flags` should be a set of flags from [`fs::file::flags`](kernel::= fs::file::flags). + fn prime_export(&self, flags: u32) -> Result> { + // SAFETY: `as_raw()` always returns a valid pointer to an initial= ized `drm_gem_object`. + let dma_ptr =3D unsafe { bindings::drm_gem_prime_export(self.as_ra= w(), flags as i32) }; + + // `drm_gem_prime_export()` returns either an error pointer, or a = valid pointer to an + // initialized `dma_buf` on success. + let dma_ptr =3D from_err_ptr(dma_ptr)?; + + // SAFETY: + // - We checked that dma_ptr is not an error, so it must point to = an initialized dma_buf + // - We used drm_gem_prime_export(), so `dma_ptr` will remain vali= d until a call to + // `drm_gem_prime_release()` which we don't call here. + let dma_buf =3D unsafe { dma_buf::DmaBuf::from_raw(dma_ptr) }; + + // INVARIANT: We used drm_gem_prime_export() to create this dma_bu= f, fulfilling the + // invariant that this dma_buf came from a GEM object of type `Sel= f`. + Ok(DmaBuf(dma_buf.into(), PhantomData)) + } + /// Creates an mmap offset to map the object from userspace. fn create_mmap_offset(&self) -> Result { // SAFETY: The arguments are valid per the type invariant. --=20 2.50.0