@@ -19,6 +19,7 @@
#include <linux/dma-fence.h>
#include <linux/dma-fence-chain.h>
#include <linux/dma-mapping.h>
+#include <linux/dma-resv.h>
#include <linux/fs.h>
#include <linux/iosys-map.h>
#include <linux/io-pgtable.h>
@@ -25,6 +25,7 @@
#include <linux/build_bug.h>
#include <linux/device.h>
#include <linux/dma-fence.h>
+#include <linux/dma-resv.h>
#include <linux/dma-fence-chain.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
@@ -437,6 +438,24 @@ void rust_helper_dma_fence_set_error(struct dma_fence *fence, int error)
}
EXPORT_SYMBOL_GPL(rust_helper_dma_fence_set_error);
+enum dma_resv_usage rust_helper_dma_resv_usage_rw(bool write)
+{
+ return dma_resv_usage_rw(write);
+}
+EXPORT_SYMBOL_GPL(rust_helper_dma_resv_usage_rw);
+
+int rust_helper_dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx *ctx)
+{
+ return dma_resv_lock(obj, ctx);
+}
+EXPORT_SYMBOL_GPL(rust_helper_dma_resv_lock);
+
+void rust_helper_dma_resv_unlock(struct dma_resv *obj)
+{
+ dma_resv_unlock(obj);
+}
+EXPORT_SYMBOL_GPL(rust_helper_dma_resv_unlock);
+
#endif
#ifdef CONFIG_DRM
new file mode 100644
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+
+//! DMA resv abstraction
+//!
+//! C header: [`include/linux/dma-resv.h`](../../include/linux/dma-resv.h)
+
+use crate::bindings;
+use crate::dma_fence::RawDmaFence;
+use crate::error::{Error, Result};
+
+/// A generic DMA Resv Object
+///
+/// # Invariants
+/// ptr is a valid pointer to a dma_resv and we own a reference to it.
+pub struct DmaResv {
+ ptr: *mut bindings::dma_resv,
+}
+
+impl DmaResv {
+ /// Create a new DmaResv object from a raw pointer to a dma_resv.
+ ///
+ /// # Safety
+ /// The caller must own a reference to the dma_resv, which is transferred to the new object.
+ pub unsafe fn from_raw(ptr: *mut bindings::dma_resv) -> Self {
+ Self { ptr }
+ }
+
+ /// Returns the implicit synchronization usage for write or read accesses.
+ pub fn usage_rw(&self, write: bool) -> bindings::dma_resv_usage {
+ // SAFETY: write is a valid bool.
+ unsafe { bindings::dma_resv_usage_rw(write) }
+ }
+
+ /// Reserve space to add fences to a dma_resv object.
+ pub fn reserve_fences(&self, num_fences: u32) -> Result {
+ // SAFETY: We own a reference to this dma_resv.
+ let ret = unsafe { bindings::dma_resv_reserve_fences(self.ptr, num_fences) };
+
+ if ret != 0 {
+ return Err(Error::from_kernel_errno(ret));
+ }
+ Ok(())
+ }
+
+ /// Add a fence to the dma_resv object
+ pub fn add_fences(
+ &self,
+ fence: &dyn RawDmaFence,
+ num_fences: u32,
+ usage: bindings::dma_resv_usage,
+ ) -> Result {
+ // SAFETY: We own a reference to this dma_resv.
+ unsafe { bindings::dma_resv_lock(self.ptr, core::ptr::null_mut()) };
+
+ let ret = self.reserve_fences(num_fences);
+ if ret.is_ok() {
+ // SAFETY: ptr is locked with dma_resv_lock(), and dma_resv_reserve_fences()
+ // has been called.
+ unsafe {
+ bindings::dma_resv_add_fence(self.ptr, fence.raw(), usage);
+ }
+ }
+
+ // SAFETY: We own a reference to this dma_resv.
+ unsafe { bindings::dma_resv_unlock(self.ptr) };
+
+ ret
+ }
+
+ /// Test if a reservation object’s fences have been signaled.
+ pub fn test_signaled(&self, usage: bindings::dma_resv_usage) -> bool {
+ // SAFETY: We own a reference to this dma_resv.
+ unsafe { bindings::dma_resv_test_signaled(self.ptr, usage) }
+ }
+}
@@ -38,6 +38,7 @@ pub mod delay;
pub mod device;
#[cfg(CONFIG_DMA_SHARED_BUFFER)]
pub mod dma_fence;
+pub mod dma_resv;
pub mod driver;
#[cfg(CONFIG_DRM = "y")]
pub mod drm;
The DMA reservation object provides a mechanism to manage a container of dma_fence object associated with a resource. So, add an abstraction to allow Rust drivers to interact with this subsystem. Signed-off-by: Maíra Canal <mcanal@igalia.com> --- rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 19 +++++++++ rust/kernel/dma_resv.rs | 75 +++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 4 files changed, 96 insertions(+) create mode 100644 rust/kernel/dma_resv.rs