From: Andreas Hindborg <a.hindborg@kernel.org>
To: "Abdiel Janulgue" <abdiel.janulgue@gmail.com>
Cc: rust-for-linux@vger.kernel.org, daniel.almeida@collabora.com,
dakr@kernel.org, robin.murphy@arm.com, aliceryhl@google.com,
"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>,
"Trevor Gross" <tmgross@umich.edu>,
"Valentin Obst" <kernel@valentinobst.de>,
"open list" <linux-kernel@vger.kernel.org>,
"Christoph Hellwig" <hch@lst.de>,
"Marek Szyprowski" <m.szyprowski@samsung.com>,
airlied@redhat.com,
"open list:DMA MAPPING HELPERS" <iommu@lists.linux.dev>
Subject: Re: [PATCH v14 03/11] samples: rust: add Rust dma test sample driver
Date: Tue, 18 Mar 2025 21:17:41 +0100 [thread overview]
Message-ID: <87h63qhz4q.fsf@kernel.org> (raw)
In-Reply-To: <03902487-5cd3-45ed-b3cb-cabfd0ac5cb7@gmail.com> (Abdiel Janulgue's message of "Tue, 18 Mar 2025 20:42:39 +0200")
"Abdiel Janulgue" <abdiel.janulgue@gmail.com> writes:
> Hi,
>
> On 18/03/2025 15:26, Andreas Hindborg wrote:
>> Abdiel Janulgue <abdiel.janulgue@gmail.com> writes:
>>
>>> Add a simple driver to excercise the basics of the Rust DMA
>>> coherent allocator bindings.
>>>
>>> Suggested-by: Danilo Krummrich <dakr@kernel.org>
>>> Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
>>> ---
>>> samples/rust/Kconfig | 11 +++++
>>> samples/rust/Makefile | 1 +
>>> samples/rust/rust_dma.rs | 97 ++++++++++++++++++++++++++++++++++++++++
>>> 3 files changed, 109 insertions(+)
>>> create mode 100644 samples/rust/rust_dma.rs
>>>
>>> diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
>>> index 3b6eae84b297..e2d14aa6beec 100644
>>> --- a/samples/rust/Kconfig
>>> +++ b/samples/rust/Kconfig
>>> @@ -78,4 +78,15 @@ config SAMPLE_RUST_HOSTPROGS
>>>
>>> If unsure, say N.
>>>
>>> +config SAMPLE_RUST_DRIVER_DMA
>>> + tristate "DMA Test Driver"
>>> + depends on PCI
>>> + help
>>> + This option builds the Rust dma test driver sample.
>>> +
>>> + To compile this as a module, choose M here:
>>> + the module will be called dma.
>>> +
>>> + If unsure, say N.
>>> +
>>> endif # SAMPLES_RUST
>>> diff --git a/samples/rust/Makefile b/samples/rust/Makefile
>>> index 0dbc6d90f1ef..1a9aff6e8d6a 100644
>>> --- a/samples/rust/Makefile
>>> +++ b/samples/rust/Makefile
>>> @@ -7,6 +7,7 @@ obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o
>>> obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o
>>> obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o
>>> obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
>>> +obj-$(CONFIG_SAMPLE_RUST_DRIVER_DMA) += rust_dma.o
>>>
>>> rust_print-y := rust_print_main.o rust_print_events.o
>>>
>>> diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs
>>> new file mode 100644
>>> index 000000000000..1740140faba6
>>> --- /dev/null
>>> +++ b/samples/rust/rust_dma.rs
>>> @@ -0,0 +1,97 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +
>>> +//! Rust DMA api test (based on QEMU's `pci-testdev`).
>>> +//!
>>> +//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
>>> +
>>> +use kernel::{bindings, dma::CoherentAllocation, pci, prelude::*};
>>> +
>>> +struct DmaSampleDriver {
>>> + pdev: pci::Device,
>>> + ca: CoherentAllocation<MyStruct>,
>>> +}
>>> +
>>> +const TEST_VALUES: [(u32, u32); 5] = [
>>> + (0xa, 0xb),
>>> + (0xc, 0xd),
>>> + (0xe, 0xf),
>>> + (0xab, 0xba),
>>> + (0xcd, 0xef),
>>> +];
>>> +
>>> +struct MyStruct {
>>> + h: u32,
>>> + b: u32,
>>> +}
>>> +
>>> +impl MyStruct {
>>> + fn new(h: u32, b: u32) -> Self {
>>> + Self { h, b }
>>> + }
>>> +}
>>> +// SAFETY: All bit patterns are acceptable values for `MyStruct`.
>>> +unsafe impl kernel::transmute::AsBytes for MyStruct {}
>>> +// SAFETY: Instances of `MyStruct` have no uninitialized portions.
>>> +unsafe impl kernel::transmute::FromBytes for MyStruct {}
>>> +
>>> +kernel::pci_device_table!(
>>> + PCI_TABLE,
>>> + MODULE_PCI_TABLE,
>>> + <DmaSampleDriver as pci::Driver>::IdInfo,
>>> + [(
>>> + pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5),
>>> + ()
>>> + )]
>>> +);
>>> +
>>> +impl pci::Driver for DmaSampleDriver {
>>> + type IdInfo = ();
>>> + const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
>>> +
>>> + fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
>>> + dev_info!(pdev.as_ref(), "Probe DMA test driver.\n");
>>> +
>>> + let ca: CoherentAllocation<MyStruct> =
>>> + CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?;
>>> +
>>> + || -> Result {
>>> + for (i, value) in TEST_VALUES.into_iter().enumerate() {
>>> + kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1));
>>> + }
>>> +
>>> + Ok(())
>>> + }()?;
>>
>> Why is this placed in a closure? Left over from deferred error for pin-init?
>>
>
> The macro expands into a block which needs to validate the function
> item_from_index()?
It is not required here, since we are already in a function that returns
result.
>
>>> +
>>> + let drvdata = KBox::new(
>>> + Self {
>>> + pdev: pdev.clone(),
>>> + ca,
>>> + },
>>> + GFP_KERNEL,
>>> + )?;
>>> +
>>> + Ok(drvdata.into())
>>> + }
>>> +}
>>> +
>>> +impl Drop for DmaSampleDriver {
>>> + fn drop(&mut self) {
>>> + dev_info!(self.pdev.as_ref(), "Unload DMA test driver.\n");
>>> +
>>> + let _ = || -> Result {
>>> + for (i, value) in TEST_VALUES.into_iter().enumerate() {
>>> + assert_eq!(kernel::dma_read!(self.ca[i].h), value.0);
>>> + assert_eq!(kernel::dma_read!(self.ca[i].b), value.1);
>>
>> We should probably change `dma_read!`/`dma_write!` to return `Result`,
>> so that we don't have to wrap these calls in a closure for obscure reasons.
>>
>
> Changing `dma_read!`/`dma_write!` to return `Result` is probably not a
> trivial change, would it be okay to have this fixed in a subsequent patch?
It is actually trivial:
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 027ef75a461a..52d235f61886 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -446,20 +446,22 @@ fn drop(&mut self) {
#[macro_export]
macro_rules! dma_read {
($dma:expr, $idx: expr, $($field:tt)*) => {{
- let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
- // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
- // dereferenced. The compiler also further validates the expression on whether `field`
- // is a member of `item` when expanded by the macro.
- unsafe {
- let ptr_field = ::core::ptr::addr_of!((*item) $($field)*);
- $crate::dma::CoherentAllocation::field_read(&$dma, ptr_field)
- }
+ (|| -> Result<_> {
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
+ // dereferenced. The compiler also further validates the expression on whether `field`
+ // is a member of `item` when expanded by the macro.
+ unsafe {
+ let ptr_field = ::core::ptr::addr_of!((*item) $($field)*);
+ ::core::result::Result::Ok($crate::dma::CoherentAllocation::field_read(&$dma, ptr_field))
+ }
+ })()
}};
($dma:ident [ $idx:expr ] $($field:tt)* ) => {
- $crate::dma_read!($dma, $idx, $($field)*);
+ $crate::dma_read!($dma, $idx, $($field)*)
};
($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {
- $crate::dma_read!($($dma).*, $idx, $($field)*);
+ $crate::dma_read!($($dma).*, $idx, $($field)*)
};
}
@@ -486,25 +488,31 @@ macro_rules! dma_read {
#[macro_export]
macro_rules! dma_write {
($dma:ident [ $idx:expr ] $($field:tt)*) => {{
- $crate::dma_write!($dma, $idx, $($field)*);
+ $crate::dma_write!($dma, $idx, $($field)*)
}};
($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {{
- $crate::dma_write!($($dma).*, $idx, $($field)*);
+ $crate::dma_write!($($dma).*, $idx, $($field)*)
}};
($dma:expr, $idx: expr, = $val:expr) => {
- let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
- // SAFETY: `item_from_index` ensures that `item` is always a valid item.
- unsafe { $crate::dma::CoherentAllocation::field_write(&$dma, item, $val) }
+ (|| -> Result {
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid item.
+ unsafe { $crate::dma::CoherentAllocation::field_write(&$dma, item, $val) }
+ ::core::result::Result::Ok(())
+ })()
};
($dma:expr, $idx: expr, $(.$field:ident)* = $val:expr) => {
- let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
- // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
- // dereferenced. The compiler also further validates the expression on whether `field`
- // is a member of `item` when expanded by the macro.
- unsafe {
- let ptr_field = ::core::ptr::addr_of_mut!((*item) $(.$field)*);
- $crate::dma::CoherentAllocation::field_write(&$dma, ptr_field, $val)
- }
+ (|| -> Result {
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
+ // dereferenced. The compiler also further validates the expression on whether `field`
+ // is a member of `item` when expanded by the macro.
+ unsafe {
+ let ptr_field = ::core::ptr::addr_of_mut!((*item) $(.$field)*);
+ $crate::dma::CoherentAllocation::field_write(&$dma, ptr_field, $val)
+ }
+ ::core::result::Result::Ok(())
+ })()
};
}
diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs
index 39b6050aa3b6..962e65322893 100644
--- a/samples/rust/rust_dma.rs
+++ b/samples/rust/rust_dma.rs
@@ -61,13 +61,10 @@ fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>
let ca: CoherentAllocation<MyStruct> =
CoherentAllocation::alloc_coherent(pdev, TEST_VALUES.len(), GFP_KERNEL)?;
- || -> Result {
- for (i, value) in TEST_VALUES.into_iter().enumerate() {
- kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1));
- }
+ for (i, value) in TEST_VALUES.into_iter().enumerate() {
+ kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?;
+ }
- Ok(())
- }()?;
let drvdata = KBox::new(
Self {
@@ -85,13 +82,10 @@ impl Drop for DmaSampleDriver {
fn drop(&mut self) {
dev_info!(self.pdev.as_ref(), "Unload DMA test driver.\n");
- let _ = || -> Result {
- for (i, value) in TEST_VALUES.into_iter().enumerate() {
- assert_eq!(kernel::dma_read!(self.ca[i].h), value.0);
- assert_eq!(kernel::dma_read!(self.ca[i].b), value.1);
- }
- Ok(())
- }();
+ for (i, value) in TEST_VALUES.into_iter().enumerate() {
+ assert_eq!(kernel::dma_read!(self.ca[i].h).unwrap(), value.0);
+ assert_eq!(kernel::dma_read!(self.ca[i].b).unwrap(), value.1);
+ }
}
}
Best regards,
Andreas Hindborg
next prev parent reply other threads:[~2025-03-18 20:17 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-11 17:47 [PATCH v14 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
2025-03-11 17:47 ` [PATCH v14 01/11] rust: error: Add EOVERFLOW Abdiel Janulgue
2025-03-11 17:47 ` [PATCH v14 02/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
2025-03-11 18:12 ` Boqun Feng
2025-03-11 21:34 ` Benno Lossin
2025-03-11 21:39 ` Boqun Feng
2025-03-17 18:51 ` Abdiel Janulgue
2025-03-21 18:25 ` Jason Gunthorpe
2025-03-21 19:40 ` Danilo Krummrich
2025-03-21 20:35 ` Boqun Feng
2025-03-11 17:47 ` [PATCH v14 03/11] samples: rust: add Rust dma test sample driver Abdiel Janulgue
2025-03-18 13:26 ` Andreas Hindborg
2025-03-18 18:42 ` Abdiel Janulgue
2025-03-18 19:06 ` Miguel Ojeda
2025-03-18 20:17 ` Andreas Hindborg [this message]
2025-03-11 17:48 ` [PATCH v14 04/11] MAINTAINERS: add entry for Rust dma mapping helpers device driver API Abdiel Janulgue
2025-03-12 12:20 ` Marek Szyprowski
2025-03-11 17:48 ` [PATCH v14 05/11] rust: dma: implement `dma::Device` trait Abdiel Janulgue
2025-03-11 17:48 ` [PATCH v14 06/11] rust: dma: add dma addressing capabilities Abdiel Janulgue
2025-03-12 3:37 ` Alexandre Courbot
2025-03-12 9:57 ` Danilo Krummrich
2025-03-18 13:35 ` Andreas Hindborg
2025-03-18 13:50 ` Andreas Hindborg
2025-03-11 17:48 ` [PATCH v14 07/11] rust: pci: implement the `dma::Device` trait Abdiel Janulgue
2025-03-11 17:48 ` [PATCH v14 08/11] rust: platform: " Abdiel Janulgue
2025-03-11 17:48 ` [PATCH v14 09/11] rust: dma: use `dma::Device` in `CoherentAllocation` Abdiel Janulgue
2025-03-18 14:01 ` Andreas Hindborg
2025-03-11 17:48 ` [PATCH v14 10/11] rust: samples: dma: set DMA mask Abdiel Janulgue
2025-03-11 17:48 ` [PATCH v14 11/11] rust: dma: add as_slice/write functions for CoherentAllocation Abdiel Janulgue
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=87h63qhz4q.fsf@kernel.org \
--to=a.hindborg@kernel.org \
--cc=abdiel.janulgue@gmail.com \
--cc=airlied@redhat.com \
--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=daniel.almeida@collabora.com \
--cc=gary@garyguo.net \
--cc=hch@lst.de \
--cc=iommu@lists.linux.dev \
--cc=kernel@valentinobst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=m.szyprowski@samsung.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 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.