drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c- Extension
.c- Size
- 27044 bytes
- Lines
- 997
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kref.hlinux/slab.hlinux/dma-fence-unwrap.hdrm/drm_exec.hdrm/drm_syncobj.hamdgpu.hamdgpu_userq_fence.h
Detected Declarations
function amdgpu_userq_fence_readfunction amdgpu_userq_fence_writefunction amdgpu_userq_fence_driver_allocfunction amdgpu_userq_walk_and_drop_fence_drvfunction amdgpu_userq_fence_driver_freefunction amdgpu_userq_fence_put_fence_drv_arrayfunction amdgpu_userq_fence_driver_processfunction list_for_each_entryfunction list_for_each_entry_safefunction amdgpu_userq_fence_driver_destroyfunction amdgpu_userq_fence_driver_getfunction amdgpu_userq_fence_driver_putfunction amdgpu_userq_fence_allocfunction amdgpu_userq_fence_initfunction amdgpu_userq_fence_signaledfunction amdgpu_userq_fence_freefunction amdgpu_userq_fence_releasefunction amdgpu_userq_fence_read_wptrfunction amdgpu_userq_fence_driver_set_errorfunction amdgpu_userq_fence_driver_force_completionfunction amdgpu_userq_signal_ioctlfunction drm_exec_until_all_lockedfunction amdgpu_userq_wait_count_fencesfunction drm_exec_until_all_lockedfunction amdgpu_userq_wait_add_fencefunction amdgpu_userq_wait_return_fence_infofunction dma_fence_unwrap_for_eachfunction drm_exec_until_all_lockedfunction dma_resv_for_each_fencefunction dma_resv_for_each_fencefunction amdgpu_userq_wait_ioctl
Annotated Snippet
if (!dma_fence_is_signaled(f)) {
dma_fence_set_error(f, -ECANCELED);
dma_fence_signal(f);
}
list_del(&fence->link);
dma_fence_put(f);
}
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
/* Free seq64 memory */
amdgpu_seq64_free(adev, fence_drv->va);
kfree(fence_drv);
}
void amdgpu_userq_fence_driver_get(struct amdgpu_userq_fence_driver *fence_drv)
{
kref_get(&fence_drv->refcount);
}
void amdgpu_userq_fence_driver_put(struct amdgpu_userq_fence_driver *fence_drv)
{
kref_put(&fence_drv->refcount, amdgpu_userq_fence_driver_destroy);
}
static int amdgpu_userq_fence_alloc(struct amdgpu_usermode_queue *userq,
struct amdgpu_userq_fence **pfence)
{
struct amdgpu_userq_fence_driver *fence_drv = userq->fence_drv;
struct amdgpu_userq_fence *userq_fence;
void *entry;
userq_fence = kmalloc(sizeof(*userq_fence), GFP_KERNEL);
if (!userq_fence)
return -ENOMEM;
/*
* Get the next unused entry, since we fill from the start this can be
* used as size to allocate the array.
*/
mutex_lock(&userq->fence_drv_lock);
XA_STATE(xas, &userq->fence_drv_xa, 0);
rcu_read_lock();
do {
entry = xas_find_marked(&xas, ULONG_MAX, XA_FREE_MARK);
} while (xas_retry(&xas, entry));
rcu_read_unlock();
userq_fence->fence_drv_array = kvmalloc_array(xas.xa_index,
sizeof(fence_drv),
GFP_KERNEL);
if (!userq_fence->fence_drv_array) {
mutex_unlock(&userq->fence_drv_lock);
kfree(userq_fence);
return -ENOMEM;
}
userq_fence->fence_drv_array_count = xas.xa_index;
xa_extract(&userq->fence_drv_xa, (void **)userq_fence->fence_drv_array,
0, ULONG_MAX, xas.xa_index, XA_PRESENT);
xa_destroy(&userq->fence_drv_xa);
mutex_unlock(&userq->fence_drv_lock);
amdgpu_userq_fence_driver_get(fence_drv);
userq_fence->fence_drv = fence_drv;
*pfence = userq_fence;
return 0;
}
static void amdgpu_userq_fence_init(struct amdgpu_usermode_queue *userq,
struct amdgpu_userq_fence *fence,
u64 seq)
{
struct amdgpu_userq_fence_driver *fence_drv = userq->fence_drv;
unsigned long flags;
bool signaled = false;
spin_lock_init(&fence->lock);
dma_fence_init64(&fence->base, &amdgpu_userq_fence_ops, &fence->lock,
fence_drv->context, seq);
/* Make sure the fence is visible to the hang detect worker */
dma_fence_put(userq->last_fence);
userq->last_fence = dma_fence_get(&fence->base);
/* Check if hardware has already processed the fence */
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
Annotation
- Immediate include surface: `linux/kref.h`, `linux/slab.h`, `linux/dma-fence-unwrap.h`, `drm/drm_exec.h`, `drm/drm_syncobj.h`, `amdgpu.h`, `amdgpu_userq_fence.h`.
- Detected declarations: `function amdgpu_userq_fence_read`, `function amdgpu_userq_fence_write`, `function amdgpu_userq_fence_driver_alloc`, `function amdgpu_userq_walk_and_drop_fence_drv`, `function amdgpu_userq_fence_driver_free`, `function amdgpu_userq_fence_put_fence_drv_array`, `function amdgpu_userq_fence_driver_process`, `function list_for_each_entry`, `function list_for_each_entry_safe`, `function amdgpu_userq_fence_driver_destroy`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.