summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
Diffstat (limited to 'rust')
-rw-r--r--rust/kernel/device.rs61
1 files changed, 59 insertions, 2 deletions
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 24e612a220f0..b591afd3d7be 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0D
+//
//! Generic devices that are part of the kernel's driver model.
//!
@@ -139,6 +140,51 @@ pub unsafe trait RawDevice {
)
};
}
+
+ fn dma_set_mask(&self, mask: u64) -> Result {
+ let dev = self.raw_device();
+ let ret = unsafe { bindings::dma_set_mask(dev as _, mask) };
+ if ret != 0 {
+ Err(Error::from_errno(ret))
+ } else {
+ Ok(())
+ }
+ }
+
+ fn dma_set_coherent_mask(&self, mask: u64) -> Result {
+ let dev = self.raw_device();
+ let ret = unsafe { bindings::dma_set_coherent_mask(dev as _, mask) };
+ if ret != 0 {
+ Err(Error::from_errno(ret))
+ } else {
+ Ok(())
+ }
+ }
+
+ fn dma_map_sg(&self, sglist: &mut [bindings::scatterlist], dir: u32) -> Result {
+ let dev = self.raw_device();
+ let count = sglist.len().try_into()?;
+ let ret = unsafe {
+ bindings::dma_map_sg_attrs(
+ dev,
+ &mut sglist[0],
+ count,
+ dir,
+ bindings::DMA_ATTR_NO_WARN.into(),
+ )
+ };
+ // TODO: It may map fewer than what was requested. What happens then?
+ if ret == 0 {
+ return Err(EIO);
+ }
+ Ok(())
+ }
+
+ fn dma_unmap_sg(&self, sglist: &mut [bindings::scatterlist], dir: u32) {
+ let dev = self.raw_device();
+ let count = sglist.len() as _;
+ unsafe { bindings::dma_unmap_sg_attrs(dev, &mut sglist[0], count, dir, 0) };
+ }
}
/// A ref-counted device.
@@ -148,7 +194,8 @@ pub unsafe trait RawDevice {
/// `ptr` is valid, non-null, and has a non-zero reference count. One of the references is owned by
/// `self`, and will be decremented when `self` is dropped.
pub struct Device {
- pub(crate) ptr: *mut bindings::device,
+ // TODO: Make this pub(crate).
+ pub ptr: *mut bindings::device,
}
// SAFETY: `Device` only holds a pointer to a C device, which is safe to be used from any thread.
@@ -178,6 +225,16 @@ impl Device {
// requirements.
unsafe { Self::new(dev.raw_device()) }
}
+
+ // TODO: Review how this is used.
+ /// Creates a new `DeviceRef` from a device whose reference count has already been incremented.
+ /// The returned object takes over the reference, that is, the reference will be decremented
+ /// when the `DeviceRef` instance goes out of scope.
+ pub fn from_dev_no_reference(dev: &dyn RawDevice) -> Self {
+ Self {
+ ptr: dev.raw_device() as _,
+ }
+ }
}
// SAFETY: The device returned by `raw_device` is the one for which we hold a reference.