Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: dma: add zeroed constructor to `Coherent`

These constructors create a coherent container of a single object
instead of slice. They are named `zeroed` and `zeroed_with_attrs` to
emphasis that they are created initialized zeroed. It is intended that
there'll be new constructors that take `PinInit` instead of zeroing.

Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260320194626.36263-4-dakr@kernel.org
[ Use kernel import style. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

authored by

Gary Guo and committed by
Danilo Krummrich
f84ecffa d9aee73c

+94 -12
+85 -8
rust/kernel/dma.rs
··· 47 47 /// # Safety 48 48 /// 49 49 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 50 - /// such as [`CoherentAllocation::alloc_attrs`]. 50 + /// such as [`Coherent::zeroed`]. 51 51 unsafe fn dma_set_mask(&self, mask: DmaMask) -> Result { 52 52 // SAFETY: 53 53 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. ··· 64 64 /// # Safety 65 65 /// 66 66 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 67 - /// such as [`CoherentAllocation::alloc_attrs`]. 67 + /// such as [`Coherent::zeroed`]. 68 68 unsafe fn dma_set_coherent_mask(&self, mask: DmaMask) -> Result { 69 69 // SAFETY: 70 70 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. ··· 83 83 /// # Safety 84 84 /// 85 85 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 86 - /// such as [`CoherentAllocation::alloc_attrs`]. 86 + /// such as [`Coherent::zeroed`]. 87 87 unsafe fn dma_set_mask_and_coherent(&self, mask: DmaMask) -> Result { 88 88 // SAFETY: 89 89 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. ··· 102 102 /// # Safety 103 103 /// 104 104 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 105 - /// such as [`CoherentAllocation::alloc_attrs`]. 105 + /// such as [`Coherent::zeroed`]. 106 106 unsafe fn dma_set_max_seg_size(&self, size: u32) { 107 107 // SAFETY: 108 108 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. ··· 202 202 /// 203 203 /// ``` 204 204 /// # use kernel::device::{Bound, Device}; 205 - /// use kernel::dma::{attrs::*, CoherentAllocation}; 205 + /// use kernel::dma::{attrs::*, Coherent}; 206 206 /// 207 207 /// # fn test(dev: &Device<Bound>) -> Result { 208 208 /// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN; 209 - /// let c: CoherentAllocation<u64> = 210 - /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?; 209 + /// let c: Coherent<[u64]> = 210 + /// Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, attribs)?; 211 211 /// # Ok::<(), Error>(()) } 212 212 /// ``` 213 213 #[derive(Clone, Copy, PartialEq)] ··· 492 492 493 493 impl<T: AsBytes + FromBytes> Coherent<T> { 494 494 /// Allocates a region of `T` of coherent memory. 495 - #[expect(unused)] 496 495 fn alloc_with_attrs( 497 496 dev: &device::Device<Bound>, 498 497 gfp_flags: kernel::alloc::Flags, ··· 526 527 cpu_addr, 527 528 dma_attrs, 528 529 }) 530 + } 531 + 532 + /// Allocates a region of type `T` of coherent memory. 533 + /// 534 + /// # Examples 535 + /// 536 + /// ``` 537 + /// # use kernel::device::{ 538 + /// # Bound, 539 + /// # Device, 540 + /// # }; 541 + /// use kernel::dma::{ 542 + /// attrs::*, 543 + /// Coherent, 544 + /// }; 545 + /// 546 + /// # fn test(dev: &Device<Bound>) -> Result { 547 + /// let c: Coherent<[u64; 4]> = 548 + /// Coherent::zeroed_with_attrs(dev, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 549 + /// # Ok::<(), Error>(()) } 550 + /// ``` 551 + #[inline] 552 + pub fn zeroed_with_attrs( 553 + dev: &device::Device<Bound>, 554 + gfp_flags: kernel::alloc::Flags, 555 + dma_attrs: Attrs, 556 + ) -> Result<Self> { 557 + Self::alloc_with_attrs(dev, gfp_flags | __GFP_ZERO, dma_attrs) 558 + } 559 + 560 + /// Performs the same functionality as [`Coherent::zeroed_with_attrs`], except the 561 + /// `dma_attrs` is 0 by default. 562 + #[inline] 563 + pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> { 564 + Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0)) 529 565 } 530 566 531 567 /// Allocates a region of `[T; len]` of coherent memory. ··· 605 571 cpu_addr, 606 572 dma_attrs, 607 573 }) 574 + } 575 + 576 + /// Allocates a zeroed region of type `T` of coherent memory. 577 + /// 578 + /// Unlike `Coherent::<[T; N]>::zeroed_with_attrs`, `Coherent::<T>::zeroed_slices` support 579 + /// a runtime length. 580 + /// 581 + /// # Examples 582 + /// 583 + /// ``` 584 + /// # use kernel::device::{ 585 + /// # Bound, 586 + /// # Device, 587 + /// # }; 588 + /// use kernel::dma::{ 589 + /// attrs::*, 590 + /// Coherent, 591 + /// }; 592 + /// 593 + /// # fn test(dev: &Device<Bound>) -> Result { 594 + /// let c: Coherent<[u64]> = 595 + /// Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 596 + /// # Ok::<(), Error>(()) } 597 + /// ``` 598 + #[inline] 599 + pub fn zeroed_slice_with_attrs( 600 + dev: &device::Device<Bound>, 601 + len: usize, 602 + gfp_flags: kernel::alloc::Flags, 603 + dma_attrs: Attrs, 604 + ) -> Result<Coherent<[T]>> { 605 + Coherent::alloc_slice_with_attrs(dev, len, gfp_flags | __GFP_ZERO, dma_attrs) 606 + } 607 + 608 + /// Performs the same functionality as [`Coherent::zeroed_slice_with_attrs`], except the 609 + /// `dma_attrs` is 0 by default. 610 + #[inline] 611 + pub fn zeroed_slice( 612 + dev: &device::Device<Bound>, 613 + len: usize, 614 + gfp_flags: kernel::alloc::Flags, 615 + ) -> Result<Coherent<[T]>> { 616 + Self::zeroed_slice_with_attrs(dev, len, gfp_flags, Attrs(0)) 608 617 } 609 618 } 610 619
+9 -4
samples/rust/rust_dma.rs
··· 6 6 7 7 use kernel::{ 8 8 device::Core, 9 - dma::{CoherentAllocation, DataDirection, Device, DmaMask}, 9 + dma::{ 10 + Coherent, 11 + DataDirection, 12 + Device, 13 + DmaMask, // 14 + }, 10 15 page, pci, 11 16 prelude::*, 12 17 scatterlist::{Owned, SGTable}, ··· 21 16 #[pin_data(PinnedDrop)] 22 17 struct DmaSampleDriver { 23 18 pdev: ARef<pci::Device>, 24 - ca: CoherentAllocation<MyStruct>, 19 + ca: Coherent<[MyStruct]>, 25 20 #[pin] 26 21 sgt: SGTable<Owned<VVec<u8>>>, 27 22 } ··· 69 64 // SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. 70 65 unsafe { pdev.dma_set_mask_and_coherent(mask)? }; 71 66 72 - let ca: CoherentAllocation<MyStruct> = 73 - CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 67 + let ca: Coherent<[MyStruct]> = 68 + Coherent::zeroed_slice(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 74 69 75 70 for (i, value) in TEST_VALUES.into_iter().enumerate() { 76 71 kernel::dma_write!(ca, [i]?, MyStruct::new(value.0, value.1));