On Thu, Aug 6, 2026 at 9:21 AM Thierry Reding <thierry.reding(a)kernel.org> wrote:
>
> On Wed, Jul 08, 2026 at 04:49:31PM -0700, T.J. Mercier wrote:
> > On Wed, Jul 1, 2026 at 9:09 AM Thierry Reding <thierry.reding(a)kernel.org> wrote:
> > >
> > > From: Thierry Reding <treding(a)nvidia.com>
> > >
> > > There is no technical reason why there should be a limited number of CMA
> > > regions, so extract some code into helpers and use them to create extra
> > > functions (cma_create() and cma_free()) that allow creating and freeing,
> > > respectively, CMA regions dynamically at runtime.
> > >
> > > The static array of CMA areas cannot be replaced by dynamically created
> > > areas because for many of them, allocation must not fail and some cases
> > > may need to initialize them before the slab allocator is even available.
> > > To account for this, keep these "early" areas in a separate list and
> > > track the dynamic areas in a separate list.
>
> Huh... going over this thread again I could've sworn that I had replied
> to this before, but I can't find any evidence of any reply.
>
> > Hi, It looks like you'll also need to update the CMA dma-buf heap's
> > add_cma_heaps init function so that it adds all the CMA areas, not
> > just the early ones.
>
> I would actually rather not do that. The case that we need this for is
> creating a special purpose dma-buf heap that's composed of multiple CMA
> areas. These areas must not be used by anyone else. Exposing these to
> the CMA dma-buf heap would allow anyone to allocate from individual
> chunks and throw off the accounting that we need to do in order to keep
> the protected memory from working correctly.
>
> Besides, given the dynamic nature of this means that the CMA dma-buf
> heap might already have probed when these dynamic CMA areas are added.
> So we would either need to have some way of notifying the CMA dma-buf
> heap of newly created areas or we might end up with an incomplete set
> of registered heaps.
>
> If you really insist, I could look into this, but I think it's actually
> a nice feature that the CMA dma-buf heap only registers these "early"
> areas and exposes them.
>
> Thierry
No problem, thanks for responding. I see there is now discussion about
subdividing a single CMA area for this, and that seems like it could
end up simpler in terms of the CMA code for this series. So I'm
supportive of that idea.
On 8/10/26 18:13, Junrui Luo via B4 Relay wrote:
> From: Junrui Luo <moonafterrain(a)outlook.com>
>
> amdgpu_userq_ensure_ev_fence() loops until the eviction fence is both
> present and unsignaled. The only producer of such a fence is
> amdgpu_evf_mgr_rearm(), which runs as the very last step of
> amdgpu_userq_vm_validate(). Every failure point ahead of it - the
> kzalloc() in the rearm itself, amdgpu_hmm_range_alloc(), the
> ttm_bo_validate() calls, the GART binding of the wptr BOs - makes
> amdgpu_userq_restore_worker() give up with only a drm_file_err().
> Nothing propagates that back, so the waiting thread reschedules the
> worker and flushes it again, forever.
>
> Both flush_delayed_work() and mutex_lock() sleep in
> TASK_UNINTERRUPTIBLE, so the looping task cannot be killed and the OOM
> killer cannot reclaim it. An unprivileged render node client
> reaches this from both AMDGPU_USERQ and AMDGPU_USERQ_SIGNAL.
>
> The eviction fence sequence number is already bumped by every
> successful rearm, so use it as the loop's progress condition: if a
> completed flush of the restore worker did not move it then no rearm
> happened and retrying cannot help. Return -ENOMEM in that case and
> let both callers report it to userspace.
>
> Fixes: a242a3e4b5be ("drm/amdgpu: simplify eviction fence suspend/resume")
> Reported-by: Yuhao Jiang <danisjiang(a)gmail.com>
> Assisted-by: Claude:claude-opus-5
> Cc: stable(a)vger.kernel.org
> Signed-off-by: Junrui Luo <moonafterrain(a)outlook.com>
Absolutely clear NAK!
This functions needs to loop forever should the rearm worker fails to re-arm the fence.
The only thing which could potentially get out of that is to kill the process or maybe that the eviction fence is signaled with an error.
Regards,
Christian.
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 21 +++++++++++++++++++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h | 4 ++--
> drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c | 10 +++++++++-
> 3 files changed, 30 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> index bec107216811..208b53ae5bd1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> @@ -448,12 +448,16 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
> * Ensures that a valid and not yet signaled eviction fence is attached to the
> * usermode queue before any queue operations proceed. If it is signalled, then
> * rearm a new eviction fence.
> + *
> + * Returns 0 with @uq_mgr->userq_mutex held, or -ENOMEM with the mutex released
> + * when the restore worker could not rearm the fence.
> */
> -void
> +int
> amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
> struct amdgpu_eviction_fence_mgr *evf_mgr)
> {
> struct dma_fence *ev_fence;
> + int seq, prev_seq = -1;
>
> retry:
> /* Flush any pending resume work to create ev_fence */
> @@ -463,7 +467,16 @@ amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
> ev_fence = amdgpu_evf_mgr_get_fence(evf_mgr);
> if (dma_fence_is_signaled(ev_fence)) {
> dma_fence_put(ev_fence);
> + seq = atomic_read(&evf_mgr->ev_fence_seq);
> mutex_unlock(&uq_mgr->userq_mutex);
> + /*
> + * The sequence number is only bumped by a successful rearm, so
> + * if the flush above ran the worker without moving it then the
> + * restore failed and looping again would never terminate.
> + */
> + if (seq == prev_seq)
> + return -ENOMEM;
> + prev_seq = seq;
> /*
> * Looks like there was no pending resume work,
> * add one now to create a valid eviction fence
> @@ -472,6 +485,8 @@ amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
> goto retry;
> }
> dma_fence_put(ev_fence);
> +
> + return 0;
> }
>
>
> @@ -747,7 +762,9 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
> if (r)
> goto clean_mqd;
>
> - amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
> + r = amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
> + if (r)
> + goto erase_doorbell;
>
> /* don't map the queue if scheduling is halted */
> if (!adev->userq_halt_for_enforce_isolation ||
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> index 6412a7f7b6ef..c35909bf7ceb 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> @@ -164,8 +164,8 @@ void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
>
> void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr);
>
> -void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr,
> - struct amdgpu_eviction_fence_mgr *evf_mgr);
> +int amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr,
> + struct amdgpu_eviction_fence_mgr *evf_mgr);
>
> u32 amdgpu_userq_get_supported_ip_mask(struct amdgpu_device *adev);
> bool amdgpu_userq_enabled(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> index 7e80442ec3e5..1c287ce59736 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
> @@ -523,7 +523,15 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
> goto put_queue;
>
> /* We are here means UQ is active, make sure the eviction fence is valid */
> - amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
> + r = amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
> + if (r) {
> + /* The fence is not initialized yet, so unwind it by hand */
> + amdgpu_userq_fence_put_fence_drv_array(fence);
> + amdgpu_userq_fence_driver_put(fence->fence_drv);
> + kvfree(fence->fence_drv_array);
> + kfree(fence);
> + goto put_queue;
> + }
>
> /* Create the new fence */
> amdgpu_userq_fence_init(queue, fence, wptr);
>
On Wed, Aug 5, 2026 at 5:01 PM Philipp Stanner <phasta(a)kernel.org> wrote:
>
> rust: types: implement ForeignOwnable for ARef<T>
> rust: sync: Add abstraction for rcu_barrier()
> rust: error: add remaining error codes
Applied (these three) to `rust-next` -- thanks everyone!
Please note that your Signed-off-by is required when sending a patch
from someone else:
https://docs.kernel.org/process/submitting-patches.html#sign-your-work-the-…
I added it here on apply for you -- please let me know if that is not
what you intended!
[ Formatted comments. Added the submitter's Signed-off-by tag. - Miguel ]
[ Relaxed `'static` bound and added `#[inline]` as discussed. Added
the submitter's Signed-off-by tag. - Miguel ]
[ Formatted documentation. Sorted tags. - Miguel ]
Thanks!
Cheers,
Miguel
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba(a)kernel.org>:
On Wed, 05 Aug 2026 13:42:42 -0700 you wrote:
> Every devmem dmabuf binding hands the page_pool PAGE_SIZE niovs today.
> On NICs that consume one descriptor per netmem, this caps a single RX
> descriptor at PAGE_SIZE and burns CPU on buffer churn.
>
> In this series, we add a bind-time netlink attribute,
> NETDEV_A_DMABUF_RX_BUF_SIZE, that lets userspace request a larger niov
> size (power of two >= PAGE_SIZE). Drivers must opt in via
> queue_mgmt_ops.QCFG_RX_PAGE_SIZE.
>
> [...]
Here is the summary with links:
- [net-next,v8,1/3] net: devmem: allow rx-page-size > PAGE_SIZE per dmabuf binding
https://git.kernel.org/netdev/net-next/c/b27a8560eec9
- [net-next,v8,2/3] selftests/net: ncdevmem: add -b option to set rx-page-size on bind
https://git.kernel.org/netdev/net-next/c/3e8c9ec4eb75
- [net-next,v8,3/3] selftests/net: devmem.py: add check_rx_large_niov
https://git.kernel.org/netdev/net-next/c/8ac4255c1e0c
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
On Fri, Aug 7, 2026 at 3:12 AM Baineng Shou <shoubaineng(a)gmail.com> wrote:
>
> Add a test case that verifies no file descriptor is leaked when
> DMA_HEAP_IOCTL_ALLOC succeeds internally but copy_to_user() fails
> to deliver the fd number back to userspace.
>
> The failure is triggered by placing the ioctl argument in a private
> anonymous page and flipping it to PROT_READ (via mprotect) between
> the kernel's copy_from_user() and copy_to_user() calls. With the
> buggy kernel the ioctl returns -EFAULT but leaves an extra open fd
> in the process's fd table; with the fixed kernel the fd count is
> unchanged.
>
> This serves as a regression test for:
> "dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds"
>
> Suggested-by: Sumit Semwal <sumit.semwal(a)linaro.org>
> Signed-off-by: Baineng Shou <shoubaineng(a)gmail.com>
Reviewed-by: T.J. Mercier <tjmercier(a)google.com>
On Wed Aug 5, 2026 at 3:59 PM BST, Philipp Stanner wrote:
> From: Danilo Krummrich <dakr(a)kernel.org>
>
> Implement ForeignOwnable for ARef<T>, making it possible for C code to
> own an ARef<T>.
>
> Since ARef represents shared ownership, BorrowedMut is &T rather than
> &mut T, matching the semantics of the underlying reference-counted type.
>
> Signed-off-by: Danilo Krummrich <dakr(a)kernel.org>
> Reviewed-by: Alice Ryhl <aliceryhl(a)google.com>
> Tested-by: Daniel Almeida <daniel.almeida(a)collabora.com>
> ---
> rust/kernel/sync/aref.rs | 40 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 40 insertions(+)
>
> diff --git a/rust/kernel/sync/aref.rs b/rust/kernel/sync/aref.rs
> index b721b2e00b98..540766613659 100644
> --- a/rust/kernel/sync/aref.rs
> +++ b/rust/kernel/sync/aref.rs
> @@ -24,6 +24,11 @@
> ptr::NonNull, //
> };
>
> +use crate::{
> + prelude::*,
> + types::ForeignOwnable, //
> +};
> +
> /// Types that are _always_ reference counted.
> ///
> /// It allows such types to define their own custom ref increment and decrement functions.
> @@ -188,6 +193,41 @@ fn eq(&self, other: &ARef<U>) -> bool {
> }
> impl<T: AlwaysRefCounted + Eq> Eq for ARef<T> {}
>
> +// SAFETY: `into_foreign` returns a pointer from `NonNull::as_ptr`, so it's non-null. The
> +// `ARef` invariant guarantees that `ptr` points to a valid `T`, so it's aligned to `T`.
> +unsafe impl<T: AlwaysRefCounted + 'static> ForeignOwnable for ARef<T> {
> + const FOREIGN_ALIGN: usize = core::mem::align_of::<T>();
> +
> + type Borrowed<'a> = &'a T;
> + type BorrowedMut<'a> = &'a T;
> +
`#[inline]` here and all others.
Best,
Gary
> + fn into_foreign(self) -> *mut c_void {
> + ARef::into_raw(self).as_ptr().cast()
> + }
> +
> + unsafe fn from_foreign(ptr: *mut c_void) -> Self {
> + // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
> + // call to `Self::into_foreign`.
> + let ptr = unsafe { NonNull::new_unchecked(ptr.cast()) };
> +
> + // SAFETY: `ptr` came from `into_foreign`, which consumed an `ARef` without decrementing
> + // the refcount, so we can transfer the ownership to the new `ARef`.
> + unsafe { ARef::from_raw(ptr) }
> + }
> +
> + unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {
> + // SAFETY: The safety requirements of this method ensure that the object remains alive and
> + // immutable for the duration of 'a.
> + unsafe { &*ptr.cast() }
> + }
> +
> + unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a T {
> + // SAFETY: The safety requirements for `borrow_mut` are a superset of the safety
> + // requirements for `borrow`.
> + unsafe { <Self as ForeignOwnable>::borrow(ptr) }
> + }
> +}
> +
> impl<T, U> PartialEq<&'_ U> for ARef<T>
> where
> T: AlwaysRefCounted + PartialEq<U>,
On 8/5/26 12:59, Pavel Begunkov wrote:
> On 8/5/26 09:27, Christian König wrote:
>>> +
>>> +Â Â Â dma_resv_lock(dmabuf->resv, NULL);
>>> +Â Â Â ctx->dev_ops->unmap(ctx, map);
>>> +Â Â Â dma_resv_unlock(dmabuf->resv);
>>> +
>>> +Â Â Â dma_fence_put(&fence->base);
>>
>> You should probably set map->fence to NULL after that.
>
> The map is freed two lines below, but I can add it as
> a defensive measure.
In that case it's ok, I've just haven't seen the kfree(map) below.
> ...
>>> +Â Â Â ret = dma_resv_reserve_fences(dmabuf->resv, 1);
>>> +Â Â Â if (WARN_ON_ONCE(ret)) {
>>> +Â Â Â Â Â Â Â struct dma_fence *fence = &map->fence->base;
>>> +
>>> +Â Â Â Â Â Â Â dma_fence_get(fence);
>>> +Â Â Â Â Â Â Â percpu_ref_kill(&map->refs);
>>> +Â Â Â Â Â Â Â dma_fence_wait(fence, false);
>>> +Â Â Â Â Â Â Â dma_fence_put(fence);
>>> +Â Â Â Â Â Â Â return;
>>> +Â Â Â }
>>> +
>>> +Â Â Â dma_resv_add_fence(dmabuf->resv, &map->fence->base,
>>> +Â Â Â Â Â Â Â Â Â Â Â Â Â Â DMA_RESV_USAGE_KERNEL);
>>
>> That sequence is clearly incorrect!
>>
>> The fence must be created after dma_resv_reserve_fences(), otherwise you definately have an illegal memory operation here.
>
> I'm not sure what you mean, can you elaborate? I only cared about
> pre-allocating it to avoid allocations here. We add / signal the fence
> only once, no reuse. The map is going to be killed here, and if we
> create a new map, it'll have its own fence.
>
> I can move the dma_fence_init() call here if that makes a difference?
Yeah that is a good start, but you might need a bit more.
Here is a summary of the usual procedure you need to follow when implementing a dma_fence backend:
1. Allocate your operation object, in this case here it's your mapping I think.
2. Prepare your operation, including all memory allocations.
3. Call dma_resv_reserve_fences() to reserve a fence slot.
4. Allocate and init your dma_fence object.
After this step no memory allocation is allowed any more until your dma_fence object signals.
The only exception is optional logging or crash dumping using GFP_NOWAIT (can fail trivially!) or minimal allocations using GFP_ATOMIC if you absolutely have to.
5. dma_resv_add_fence() to publish the fence.
6. dma_resv_unlock().
Having a dma_fence is certainly nice to have, but the tricky part is that memory allocations using GFP_KERNEL (or GFP_IO, GFP_FS etc...) can cycle back and wait for your dma_fence to signal which essentially can cause a deadlock very deeply inside memory management.
Since those deadlocks happen only on memory contention situations they are usually just hard to reproduce but still totally break your neck if you manage to mess this up. So that needs to be super carefully implemented.
Regards,
Christian.
On Wed Aug 5, 2026 at 3:59 PM BST, Philipp Stanner wrote:
> rcu_barrier() is a frequently used C function which is always safe to be
> called.
>
> Add a safe abstraction for rcu_barrier().
>
> Signed-off-by: Philipp Stanner <phasta(a)kernel.org>
> Tested-by: Daniel Almeida <daniel.almeida(a)collabora.com>
Acked-by: Gary Guo <gary(a)garyguo.net>
> ---
> rust/kernel/sync/rcu.rs | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/rust/kernel/sync/rcu.rs b/rust/kernel/sync/rcu.rs
> index a32bef6e490b..7031ca5d2473 100644
> --- a/rust/kernel/sync/rcu.rs
> +++ b/rust/kernel/sync/rcu.rs
> @@ -50,3 +50,23 @@ fn drop(&mut self) {
> pub fn read_lock() -> Guard {
> Guard::new()
> }
> +
> +/// Wait until all in-flight call_rcu() callbacks complete.
This misses some `` quoting but these can be applied on fixup.
Best,
Gary
> +///
> +/// Note that this primitive does not necessarily wait for an RCU grace period
> +/// to complete. For example, if there are no RCU callbacks queued anywhere
> +/// in the system, then rcu_barrier() is within its rights to return
> +/// immediately, without waiting for anything, much less an RCU grace period.
> +/// In fact, rcu_barrier() will normally not result in any RCU grace periods
> +/// beyond those that were already destined to be executed.
> +///
> +/// In kernels built with CONFIG_RCU_LAZY=y, this function also hurries all
> +/// pending lazy RCU callbacks.
> +///
> +/// Note that this is one of the RCU primitives which must not be called in
> +/// atomic context.
> +#[inline]
> +pub fn rcu_barrier() {
> + // SAFETY: `rcu_barrier()` is always safe to be called. It just might wait for a grace period.
> + unsafe { bindings::rcu_barrier() };
> +}