A FenceCallbackRegistration invokes the on_signal() trait functions specified by the user.
These callbacks always get executed, even if the fence was signaled with an error. The user must then be able to react accordingly. Since the fence->error must only be set before a fence signals, and must not change after it signaled, we better acquire it with the lock. Change the on_signal() trait function so that the user always gets passed the fence's actual state. Signed-off-by: Philipp Stanner <[email protected]> --- rust/kernel/dma_buf/dma_fence.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/rust/kernel/dma_buf/dma_fence.rs b/rust/kernel/dma_buf/dma_fence.rs index 71965b26e148..c8856dbed0a2 100644 --- a/rust/kernel/dma_buf/dma_fence.rs +++ b/rust/kernel/dma_buf/dma_fence.rs @@ -291,9 +291,12 @@ fn from(e: AllocError) -> Self { /// } /// /// impl FenceCallback for MyCallback { -/// fn on_signal(&mut self) { -/// pr_info!("Fence signaled!\n"); -/// // Handle fence completion +/// fn on_signal(&mut self, status: Result) { +/// if status.is_ok() { +/// pr_info!("Fence signaled!\n"); +/// } else { +/// pr_err!("Fence signaled with an error!\n"); +/// } /// } /// } /// ``` @@ -308,7 +311,7 @@ pub trait FenceCallback: Send { /// An implementation likely wants to inform itself (e.g., through a work item) /// within this callback that the associated [`FenceCallbackRegistration`] /// can now be dropped. - fn on_signal(&mut self); + fn on_signal(&mut self, status: Result); } /// A callback registration on a fence. @@ -395,11 +398,18 @@ pub unsafe fn new<'a>( // embedded into a `FenceCallbackRegistration`. let reg: *mut Self = unsafe { container_of!(ptr, Self, callback_foreign) }; + // SAFETY: The lock is being held by the C backend. + let fence_result = match unsafe { (*reg).fence.status_locked() } { + FenceStatus::Signaled(result) => result, + // Can never happen. + FenceStatus::Unsignaled => Err(ENOENT), + }; + // SAFETY: `reg` is a valid `Self` pointer. // // The backend ensures synchronisation so whoever holds the registration object cannot drop // it while this code is running. See `FenceCallbackRegistration::drop`. - unsafe { (*reg).callback.on_signal() }; + unsafe { (*reg).callback.on_signal(fence_result) }; } /// Returns a reference to the fence this callback is registered on. @@ -678,8 +688,12 @@ struct DriverFenceData<'a, T: Send + Sync + FenceContextOps> { /// struct CallbackData { } /// /// impl FenceCallback for CallbackData { -/// fn on_signal(&mut self) { -/// pr_info!("DmaFence callback executed.\n"); +/// fn on_signal(&mut self, status: Result) { +/// if status.is_ok() { +/// pr_info!("DmaFence callback executed.\n"); +/// else { +/// pr_err!("DmaFence callback executed, but fence has an error.\n"); +/// } /// } /// } /// -- 2.56.0
