@@ -2,10 +2,13 @@
use core::fmt::Write;
use core::ops::Deref;
-use kernel::c_str;
+use core::time::Duration;
use kernel::dma_fence::*;
use kernel::prelude::*;
use kernel::sync::Arc;
+use kernel::time::timer::*;
+use kernel::time::*;
+use kernel::{bindings, c_str, timer_init};
static QUEUE_NAME: &CStr = c_str!("vgem_fence");
static QUEUE_CLASS_KEY: kernel::sync::LockClassKey = kernel::sync::LockClassKey::new();
@@ -36,6 +39,7 @@ impl FenceOps for Fence {
pub(crate) struct VgemFence {
fence: Arc<UniqueFence<Fence>>,
+ _timer: Box<FnTimer<Box<dyn FnMut() -> Result<Next> + Sync>>>,
}
impl VgemFence {
@@ -43,7 +47,30 @@ impl VgemFence {
let fence_ctx = FenceContexts::new(1, QUEUE_NAME, &QUEUE_CLASS_KEY)?;
let fence = Arc::try_new(fence_ctx.new_fence(0, Fence {})?)?;
- Ok(Self { fence })
+ // SAFETY: The caller calls [`FnTimer::init_timer`] before using the timer.
+ let t = Box::try_new(unsafe {
+ FnTimer::new(Box::try_new({
+ let fence = fence.clone();
+ move || {
+ let _ = fence.signal();
+ Ok(Next::Done)
+ }
+ })? as Box<_>)
+ })?;
+
+ // SAFETY: As FnTimer is inside a Box, it won't be moved.
+ let ptr = unsafe { core::pin::Pin::new_unchecked(&*t) };
+
+ timer_init!(ptr, 0, "vgem_timer");
+
+ // SAFETY: Duration.as_millis() returns a valid total number of whole milliseconds.
+ let timeout =
+ unsafe { bindings::msecs_to_jiffies(Duration::from_secs(10).as_millis().try_into()?) };
+
+ // We force the fence to expire within 10s to prevent driver hangs
+ ptr.raw_timer().schedule_at(jiffies_later(timeout));
+
+ Ok(Self { fence, _timer: t })
}
}
@@ -33,6 +33,10 @@ impl File {
/// via the dma-buf reservation object and visible to consumers of the exported
/// dma-buf.
///
+ /// This returns the handle for the new fence that must be signaled within 10
+ /// seconds (or otherwise it will automatically expire). See
+ /// signal (DRM_IOCTL_VGEM_FENCE_SIGNAL).
+ ///
/// If the vGEM handle does not exist, attach returns -ENOENT.
///
pub(crate) fn attach(
@@ -84,6 +88,9 @@ impl File {
/// Signal and consume a fence earlier attached to a vGEM handle using
/// attach (DRM_IOCTL_VGEM_FENCE_ATTACH).
///
+ /// All fences must be signaled within 10s of attachment or otherwise they
+ /// will automatically expire (and signal returns -ETIMEDOUT).
+ ///
/// Signaling a fence indicates to all consumers of the dma-buf that the
/// client has completed the operation associated with the fence, and that the
/// buffer is then ready for consumption.
In order to prevent possible hangs, if the fence is not signaled for more than 10 seconds, force the fence to expire by being signaled. Signed-off-by: Maíra Canal <mcanal@igalia.com> --- drivers/gpu/drm/rustgem/fence.rs | 31 +++++++++++++++++++++++++++++-- drivers/gpu/drm/rustgem/file.rs | 7 +++++++ 2 files changed, 36 insertions(+), 2 deletions(-)