From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Alexandre Courbot" <acourbot@nvidia.com>,
"Abdiel Janulgue" <abdiel.janulgue@gmail.com>, <dakr@kernel.org>,
<lyude@redhat.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Valentin Obst" <kernel@valentinobst.de>,
"open list" <linux-kernel@vger.kernel.org>,
"Marek Szyprowski" <m.szyprowski@samsung.com>,
"Robin Murphy" <robin.murphy@arm.com>,
airlied@redhat.com, rust-for-linux@vger.kernel.org,
"open list:DMA MAPPING HELPERS" <iommu@lists.linux.dev>,
"Petr Tesarik" <petr@tesarici.cz>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Herbert Xu" <herbert@gondor.apana.org.au>,
"Sui Jingfeng" <sui.jingfeng@linux.dev>,
"Randy Dunlap" <rdunlap@infradead.org>,
"Michael Kelley" <mhklinux@outlook.com>
Subject: Re: [RFC PATCH 1/2] rust: add initial scatterlist bindings
Date: Wed, 14 May 2025 21:50:15 +0900 [thread overview]
Message-ID: <D9VWA9ZQLY85.277DFA3YTH5R0@nvidia.com> (raw)
In-Reply-To: <D9VQQAY6G20X.RVU8H169KQL2@nvidia.com>
On Wed May 14, 2025 at 5:29 PM JST, Alexandre Courbot wrote:
>> +/// The base interface for a scatter-gather table of DMA address spans.
>> +///
>> +/// This structure represents the Rust abstraction for a C `struct sg_table`. This implementation
>> +/// abstracts the usage of an already existing C `struct sg_table` within Rust code that we get
>> +/// passed from the C side.
>> +///
>> +/// # Invariants
>> +///
>> +/// The `sg_table` pointer is valid for the lifetime of an SGTable instance.
>> +#[repr(transparent)]
>> +pub struct SGTable(Opaque<bindings::sg_table>);
>> +
>> +impl SGTable {
>> + /// Convert a raw `struct sg_table *` to a `&'a SGTable`.
>> + ///
>> + /// # Safety
>> + ///
>> + /// Callers must ensure that the `struct sg_table` pointed to by `ptr` is initialized and valid for
>> + /// the lifetime of the returned reference.
>> + pub unsafe fn as_ref<'a>(ptr: *mut bindings::sg_table) -> &'a Self {
>> + // SAFETY: Guaranteed by the safety requirements of the function.
>> + unsafe { &*ptr.cast() }
>> + }
>> +
>> + /// Obtain the raw `struct sg_table *`.
>> + pub fn as_raw(&self) -> *mut bindings::sg_table {
>> + self.0.get()
>> + }
>> +
>> + /// Returns a mutable iterator over the scather-gather table.
>> + pub fn iter_mut(&mut self) -> SGTableIterMut<'_> {
>> + SGTableIterMut {
>> + // SAFETY: dereferenced pointer is valid due to the type invariants on `SGTable`.
>> + pos: Some(unsafe { SGEntry::as_mut((*self.0.get()).sgl) }),
>> + }
>> + }
>> +
>> + /// Returns an iterator over the scather-gather table.
>> + pub fn iter(&self) -> SGTableIter<'_> {
>> + SGTableIter {
>> + // SAFETY: dereferenced pointer is valid due to the type invariants on `SGTable`.
>> + pos: Some(unsafe { SGEntry::as_ref((*self.0.get()).sgl) }),
>> + }
>> + }
>
> I think Jason mentioned this already, but you should really have two
> iterators, one for the CPU side and one for the device side. The two
> lists are not even guaranteed to be the same size IIUC, so having both
> lists in the same iterator is a receipe for confusion and bugs.
>
> I have an (absolutely awful) implementation of that if you want to take
> a look:
>
> https://github.com/Gnurou/linux/blob/nova-gsp/drivers/gpu/nova-core/firmware/radix3.rs#L200
>
> It's probably wrong in many places, and I just wrote it as a temporary
> alternative until this series lands, but please steal any idea that you
> think is reusable.
>
> There is also the fact that SG tables are not always necessarily mapped
> on the device side, so we would have to handle that as well, e.g.
> through a typestate or maybe by just returning a dedicated error in that
> case.
Gave this some more thought, and basically it appears this is a
two-parts problem:
1) Iterating over an already-existing sg_table (which might have been
created by your `as_ref` function, although as Daniel suggested it
needs a better name),
2) Building a sg_table.
The C API for both is a bit quirky, but 1) looks the most pressing to
address and should let us jump to 2) with a decent base.
Since an sg_table can exist in two states (mapped or unmapped), I think
it is a good candidate for the typestate pattern, i.e. `SgTable` can be
either `SgTable<Unmapped>` or `SgTable<Mapped>`, the state allowing us
to limit the availability of some methods. For instance, an iterator
over the DMA addresses only makes sense in the `Mapped` state.
A `SgTable<Unmapped>` can turn into a `SgTable<Mapped>` through its
`map(self, device: &Device)` method (and vice-versa via an `unmap`
method for `SgTable<Mapped>`. This has the benefit of not binding the
`SgTable` to a device until we need to map it. `SgTable<Unmapped>` could
also implement `Clone` for convenience, but not `SgTable<Mapped>`.
Then there are the iterators. All SgTables can iterate over the CPU
addresses, but only `SgTable<Mapped>` provides a DMA addresses iterator.
The items for each iterator would be their own type, containing only the
information needed (or references to the appropriate fields of the
`struct scatterlist`).
Mapped tables should be immutable, so a mutable iterator to CPU
addresses would only be provided in the `Unmapped` state - if we want
to allow mutability at all.
Because the tricky part of building or modifying a SG table is
preventing it from reaching an invalid state. I don't have a good idea
yet of how this should be done, and there are many different ways to
build a SG table - one or several builder types can be involved here,
that output the `SgTable` in their final stage. Probably people more
acquainted with the scatterlist API have ideas.
next prev parent reply other threads:[~2025-05-14 12:50 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-12 9:53 [RFC PATCH 0/2] scatterlist rust bindings Abdiel Janulgue
2025-05-12 9:53 ` [RFC PATCH 1/2] rust: add initial scatterlist bindings Abdiel Janulgue
2025-05-12 11:39 ` Daniel Almeida
2025-05-15 19:26 ` Lyude Paul
2025-05-15 21:11 ` Danilo Krummrich
2025-05-16 16:57 ` Daniel Almeida
2025-05-16 17:55 ` Danilo Krummrich
2025-05-12 16:42 ` Jason Gunthorpe
2025-05-12 20:01 ` Daniel Almeida
2025-05-12 20:10 ` Danilo Krummrich
2025-05-14 8:29 ` Alexandre Courbot
2025-05-14 12:50 ` Alexandre Courbot [this message]
2025-05-16 7:52 ` Abdiel Janulgue
2025-05-15 20:01 ` Lyude Paul
2025-05-16 7:52 ` Abdiel Janulgue
2025-05-26 13:04 ` Abdiel Janulgue
2025-05-12 9:53 ` [RFC PATCH 2/2] samples: rust: add sample code for " Abdiel Janulgue
2025-05-12 11:19 ` [RFC PATCH 0/2] scatterlist rust bindings Daniel Almeida
2025-05-14 7:00 ` Abdiel Janulgue
2025-05-14 12:12 ` Marek Szyprowski
2025-05-16 7:47 ` Abdiel Janulgue
2025-05-13 2:19 ` Herbert Xu
2025-05-13 5:50 ` Christoph Hellwig
2025-05-13 7:38 ` Petr Tesařík
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=D9VWA9ZQLY85.277DFA3YTH5R0@nvidia.com \
--to=acourbot@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=abdiel.janulgue@gmail.com \
--cc=airlied@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=herbert@gondor.apana.org.au \
--cc=iommu@lists.linux.dev \
--cc=kernel@valentinobst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=lyude@redhat.com \
--cc=m.szyprowski@samsung.com \
--cc=mhklinux@outlook.com \
--cc=ojeda@kernel.org \
--cc=petr@tesarici.cz \
--cc=rdunlap@infradead.org \
--cc=robin.murphy@arm.com \
--cc=rust-for-linux@vger.kernel.org \
--cc=sui.jingfeng@linux.dev \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.