linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Danilo Krummrich" <dakr@kernel.org>
To: "Alexandre Courbot" <acourbot@nvidia.com>
Cc: <akpm@linux-foundation.org>, <ojeda@kernel.org>,
	<alex.gaynor@gmail.com>, <boqun.feng@gmail.com>,
	<gary@garyguo.net>, <bjorn3_gh@protonmail.com>,
	<lossin@kernel.org>, <a.hindborg@kernel.org>,
	<aliceryhl@google.com>, <tmgross@umich.edu>,
	<abdiel.janulgue@gmail.com>, <jgg@ziepe.ca>, <lyude@redhat.com>,
	<robin.murphy@arm.com>, <daniel.almeida@collabora.com>,
	<rust-for-linux@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v3 3/5] rust: scatterlist: Add abstraction for sg_table
Date: Wed, 27 Aug 2025 01:38:13 +0200	[thread overview]
Message-ID: <DCCR71R83O68.11AA6B36TYQ3C@kernel.org> (raw)
In-Reply-To: <DCCGKLKK0D08.1VOAVWOJIXIIO@kernel.org>

On Tue Aug 26, 2025 at 5:18 PM CEST, Danilo Krummrich wrote:
> On Tue Aug 26, 2025 at 4:36 PM CEST, Alexandre Courbot wrote:
>> Even if this is for internal use, I think a short comment explaining
>> what this is for, and why it needs to be pinned (pointed to by devres)
>
> That's not the reason this structure needs to be pinned. This is the reason for
> Devres itself needs to be pinned.
>
> In fact, I think RawSGTable by itself does not need to be pinned.

Just to expand on this a bit:

Eventually it does need to be pinned, because DmaMappedSgt keeps a pointer of
the underlying struct sg_table. But, this happens in Owned:

	Ok(try_pin_init!(&this in Self {
	    // SAFETY:
	    // - `page_vec` is a `KVec` of valid `struct page *` obtained from `pages`.
	    // - The pages contained in `pages` remain valid for the entire lifetime of the
	    //   `RawSGTable`.
	    sgt: unsafe { RawSGTable::new(&mut page_vec, size, max_segment, flags) }?,
	    dma <- {
	        // SAFETY: `this` is a valid pointer to uninitialized memory.
	        let sgt = unsafe { &raw mut (*this.as_ptr()).sgt }.cast();
	
	        // SAFETY: `sgt` is guaranteed to be non-null.
	        let sgt = unsafe { NonNull::new_unchecked(sgt) };
	
	        // SAFETY:
	        // - It is guaranteed that the object returned by `DmaMappedSgt::new` won't out-live
	        //   `sgt`.
	        // - `sgt` is never DMA unmapped manually.
	        Devres::new(dev, unsafe { DmaMappedSgt::new(sgt, dev, dir) })
	    },
	    _pages: pages,
	}))

So, it's fine to move RawSGTable around, *until* we obtain the address for
DmaMappedSgt (within Owned, Devres<DmaMappedSgt> is dropped before the
RawSGTable). However, this is an implementation detail of Owned and has nothing
to do with RawSGTable by itself.

Hence, we could also nuke #[pin_data] for RawSGTable and implement it as:

	/// A transparent wrapper around a `struct sg_table`.
	///
	/// While we could also create the `struct sg_table` in the constructor of [`Owned`], we can't tear
	/// down the `struct sg_table` in [`Owned::drop`]; the drop order in [`Owned`] matters.
	#[repr(transparent)]
	struct RawSGTable(Opaque<bindings::sg_table>);

	impl RawSGTable {
	    /// # Safety
	    ///
	    /// - `pages` must be a slice of valid `struct page *`.
	    /// - The pages pointed to by `pages` must remain valid for the entire lifetime of the returned
	    ///   [`RawSGTable`].
	    unsafe fn new(
	        pages: &mut [*mut bindings::page],
	        size: usize,
	        max_segment: u32,
	        flags: alloc::Flags,
	    ) -> Result<Self> {
	        // `sg_alloc_table_from_pages_segment()` expects at least one page, otherwise it
	        // produces a NPE.
	        if pages.is_empty() {
	            return Err(EINVAL);
	        }
	
	        let sgt = Opaque::zeroed();
	
	        // SAFETY:
	        // - `sgt.get()` is a valid pointer to uninitialized memory.
	        // - As by the check above, `pages` is not empty.
	        error::to_result(unsafe {
	            bindings::sg_alloc_table_from_pages_segment(
	                sgt.get(),
	                pages.as_mut_ptr(),
	                pages.len().try_into()?,
	                0,
	                size,
	                max_segment,
	                flags.as_raw(),
	            )
	        })?;
	
	        Ok(Self(sgt))
	    }
	
	    #[inline]
	    fn as_raw(&self) -> *mut bindings::sg_table {
	        self.0.get()
	    }
	}
	
	impl Drop for RawSGTable {
	    #[inline]
	    fn drop(&mut self) {
	        // SAFETY: `sgt` is a valid and initialized `struct sg_table`.
	        unsafe { bindings::sg_free_table(self.0.get()) };
	    }
	}

  parent reply	other threads:[~2025-08-26 23:38 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-25 13:24 [PATCH v3 0/5] Rust infrastructure for sg_table and scatterlist Danilo Krummrich
2025-08-25 13:24 ` [PATCH v3 1/5] rust: dma: implement DataDirection Danilo Krummrich
2025-08-26 17:10   ` Daniel Almeida
2025-08-25 13:24 ` [PATCH v3 2/5] rust: dma: add type alias for bindings::dma_addr_t Danilo Krummrich
2025-08-26 17:15   ` Daniel Almeida
2025-08-26 17:33     ` Danilo Krummrich
2025-08-26 19:58       ` Daniel Almeida
2025-08-25 13:24 ` [PATCH v3 3/5] rust: scatterlist: Add abstraction for sg_table Danilo Krummrich
2025-08-26 14:16   ` Alice Ryhl
2025-08-26 14:32     ` Danilo Krummrich
2025-08-26 17:41       ` Daniel Almeida
2025-08-26 14:36   ` Alexandre Courbot
2025-08-26 15:18     ` Danilo Krummrich
2025-08-26 17:45       ` Daniel Almeida
2025-08-26 23:38       ` Danilo Krummrich [this message]
2025-08-27  8:30       ` Alexandre Courbot
2025-08-26 17:40   ` Daniel Almeida
2025-08-26 19:13     ` Danilo Krummrich
2025-08-26 20:16       ` Daniel Almeida
2025-08-26 20:27         ` Danilo Krummrich
2025-08-25 13:24 ` [PATCH v3 4/5] samples: rust: dma: add sample code for SGTable Danilo Krummrich
2025-08-26 14:38   ` Alexandre Courbot
2025-08-26 17:46   ` Daniel Almeida
2025-08-25 13:24 ` [PATCH v3 5/5] MAINTAINERS: rust: dma: add scatterlist files Danilo Krummrich
2025-08-28 10:19   ` Miguel Ojeda
2025-08-26 21:01 ` [PATCH v3 0/5] Rust infrastructure for sg_table and scatterlist Lyude Paul

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=DCCR71R83O68.11AA6B36TYQ3C@kernel.org \
    --to=dakr@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=abdiel.janulgue@gmail.com \
    --cc=acourbot@nvidia.com \
    --cc=akpm@linux-foundation.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=daniel.almeida@collabora.com \
    --cc=gary@garyguo.net \
    --cc=jgg@ziepe.ca \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=lyude@redhat.com \
    --cc=ojeda@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=rust-for-linux@vger.kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).