Skip to content

Commit 9e24bed

Browse files
Danilo Krummrichjannau
authored andcommitted
rust: dma: add dma addressing capabilities
Implement `dma_set_mask()` and `dma_set_mask_and_coherent()` in the `dma::Device` trait. Those methods are used to inform the kernel about the device's DMA addressing capabilities. Co-developed-by: Abdiel Janulgue <abdiel.janulgue@gmail.com> Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com> Signed-off-by: Danilo Krummrich <dakr@kernel.org>
1 parent fb95378 commit 9e24bed

3 files changed

Lines changed: 52 additions & 3 deletions

File tree

rust/helpers/dma.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/dma-mapping.h>
4+
5+
int rust_helper_dma_set_mask_and_coherent(struct device *dev, u64 mask)
6+
{
7+
return dma_set_mask_and_coherent(dev, mask);
8+
}

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "build_bug.c"
1414
#include "cred.c"
1515
#include "device.c"
16+
#include "dma.c"
1617
#include "err.c"
1718
#include "fs.c"
1819
#include "io.c"

rust/kernel/dma.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
//! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h)
66
77
use crate::{
8-
bindings, build_assert,
9-
device,
8+
bindings, build_assert, device,
109
error::code::*,
1110
error::Result,
11+
prelude::*,
1212
transmute::{AsBytes, FromBytes},
1313
types::ARef,
1414
};
@@ -18,7 +18,35 @@ use crate::{
1818
/// The [`Device`] trait should be implemented by bus specific device representations, where the
1919
/// underlying bus has potential support for DMA, such as [`crate::pci::Device`] or
2020
/// [crate::platform::Device].
21-
pub trait Device: AsRef<device::Device> {}
21+
pub trait Device: AsRef<device::Device> {
22+
/// Inform the kernel about the device's DMA addressing capabilities.
23+
///
24+
/// Set both the DMA mask and the coherent DMA mask to the same value.
25+
///
26+
/// Note that we don't check the return value from the C `dma_set_coherent_mask` as the DMA API
27+
/// guarantees that the coherent DMA mask can be set to the same or smaller than the streaming
28+
/// DMA mask.
29+
fn dma_set_mask_and_coherent(&mut self, mask: u64) -> Result {
30+
// SAFETY: By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
31+
let ret = unsafe { bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask) };
32+
if ret != 0 {
33+
Err(Error::from_errno(ret))
34+
} else {
35+
Ok(())
36+
}
37+
}
38+
39+
/// Same as [`Self::dma_set_mask_and_coherent`], but set the mask only for streaming mappings.
40+
fn dma_set_mask(&mut self, mask: u64) -> Result {
41+
// SAFETY: By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
42+
let ret = unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask) };
43+
if ret != 0 {
44+
Err(Error::from_errno(ret))
45+
} else {
46+
Ok(())
47+
}
48+
}
49+
}
2250

2351
/// Possible attributes associated with a DMA mapping.
2452
///
@@ -392,3 +420,15 @@ macro_rules! dma_write {
392420
}
393421
};
394422
}
423+
424+
/// Helper function to set the bit mask for DMA addressing.
425+
pub const fn dma_bit_mask(n: usize) -> u64 {
426+
if n > 64 {
427+
return 0;
428+
}
429+
if n == 64 {
430+
!0
431+
} else {
432+
(1 << (n)) - 1
433+
}
434+
}

0 commit comments

Comments
 (0)