diff options
-rw-r--r-- | rust/kernel/device.rs | 61 |
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. |