Add the per-file WAIT_EVENT manager and lifetime plumbing used to store and retrieve event records for render-node clients.
The manager maintains a list of pending WAIT_EVENT records, supports blocking waits from userspace, copies the first matching event record to userspace, and enforces single-consumer semantics by removing records once they are consumed. Register the WAIT_EVENT ioctl so render-node clients can access the per-file WAIT_EVENT manager. For queue-scoped events, queue_id is resolved to the corresponding usermode queue object at the ioctl boundary. Pending records are matched internally using queue pointer equality, while queue_id remains a userspace identifier used only at the UAPI boundary and returned in event metadata. WAIT_EVENT uses an absolute CLOCK_MONOTONIC deadline for timeout handling. The remaining timeout is recomputed after each wakeup so that interrupted or spurious wakeups continue to honor the original userspace deadline. Pending WAIT_EVENT records hold queue references while queued. Those references are released when records are consumed, explicitly removed, or destroyed during manager teardown. Embed the WAIT_EVENT manager in amdgpu_fpriv and tie its lifetime to drm_file. During teardown, the manager is marked dead before pending records are detached and blocked waiters are awakened, preventing new records from being queued while shutdown is in progress. The USERQ manager is torn down before the embedded WAIT_EVENT manager is finalized, so queues are removed from the producer lookup paths before the manager can go out of scope. This existing teardown ordering provides the lifetime guarantee for WAIT_EVENT producers without requiring an additional manager reference. Changes since v11: - Use an unsigned absolute CLOCK_MONOTONIC deadline. - Recompute the remaining timeout after each wakeup. - Preserve a zero timeout as an immediate check-and-return, as suggested by Christian. - Remove the MAX_SCHEDULE_TIMEOUT special handling. - Simplify queue reference cleanup using unconditional amdgpu_userq_put(). - Clarify that queue pointers are used internally for event matching, while queue_id remains a userspace-only identifier. - Improve kerneldoc describing manager state, event matching, and teardown ordering. - Document the existing teardown ordering that guarantees the embedded WAIT_EVENT manager remains valid while USERQ producers are active. Cc: Alex Deucher <[email protected]> Cc: Christian König <[email protected]> Signed-off-by: Srinivasan Shanmugam <[email protected]> --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 5 +- .../gpu/drm/amd/amdgpu/amdgpu_wait_event.c | 410 ++++++++++++++++++ .../gpu/drm/amd/amdgpu/amdgpu_wait_event.h | 101 +++++ 6 files changed, 521 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index b7897f98436c..c4cee6a6bc64 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -72,7 +72,7 @@ amdgpu-y += amdgpu_device.o amdgpu_reg_access.o amdgpu_doorbell_mgr.o amdgpu_kms amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o amdgpu_lockdep.o \ amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_dev_coredump.o \ amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o \ - amdgpu_wb.o amdgpu_cwsr.o amdgpu_events.o amdgpu_eventfd.o + amdgpu_wb.o amdgpu_cwsr.o amdgpu_events.o amdgpu_eventfd.o amdgpu_wait_event.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4f42888e2647..91f1dc737aee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -104,6 +104,7 @@ #include "amdgpu_fdinfo.h" #include "amdgpu_mca.h" #include "amdgpu_eventfd.h" +#include "amdgpu_wait_event.h" #include "amdgpu_ras.h" #include "amdgpu_lockdep.h" #include "amdgpu_cper.h" @@ -427,13 +428,15 @@ struct amdgpu_fpriv { uint32_t xcp_id; struct amdgpu_eventfd_mgr eventfd_mgr; + struct amdgpu_wait_event_mgr wait_event_mgr; }; struct drm_device; struct drm_file; int amdgpu_eventfd_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); - +int amdgpu_wait_event_drm_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv); /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index e90cf67c1cd8..b738a1bdf9d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -3097,6 +3097,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { DRM_IOCTL_DEF_DRV(AMDGPU_GEM_LIST_HANDLES, amdgpu_gem_list_handles_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_PROC_OPTIONS, amdgpu_proc_options_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_EVENTFD, amdgpu_eventfd_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_EVENT, amdgpu_wait_event_drm_ioctl, DRM_RENDER_ALLOW), }; static const struct drm_driver amdgpu_kms_driver = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index ccc9c3f8aba7..72bea83d7408 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1681,6 +1681,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) } amdgpu_eventfd_mgr_init(&fpriv->eventfd_mgr); + amdgpu_wait_event_mgr_init(&fpriv->wait_event_mgr); pasid = amdgpu_pasid_alloc(16); if (pasid < 0) { @@ -1754,6 +1755,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) if (pasid) amdgpu_pasid_free(pasid); + amdgpu_wait_event_mgr_fini(&fpriv->wait_event_mgr); kfree(fpriv); out_suspend: @@ -1784,8 +1786,9 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (!fpriv) return; - /* Drop all subscriptions before fpriv goes away. */ + /* Drop eventfd subscriptions and pending wait-event records. */ amdgpu_eventfd_mgr_fini(&fpriv->eventfd_mgr); + amdgpu_wait_event_mgr_fini(&fpriv->wait_event_mgr); pm_runtime_get_sync(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c new file mode 100644 index 000000000000..7060828be08d --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <linux/jiffies.h> +#include <linux/sched/signal.h> +#include <linux/slab.h> +#include <linux/timekeeping.h> +#include <linux/uaccess.h> + +#include "amdgpu.h" +#include "amdgpu_userq_internal.h" +#include "amdgpu_wait_event.h" + +/** + * amdgpu_wait_event_deadline_to_jiffies - calculate remaining wait time + * @deadline_ns: absolute CLOCK_MONOTONIC deadline in nanoseconds + * + * Convert an absolute CLOCK_MONOTONIC deadline into the remaining number + * of jiffies. + * + * The caller recalculates the remaining time after every wakeup so that + * interrupted or spurious wakeups continue to honor the original + * userspace deadline. + * + * Return: + * Remaining wait time in jiffies. Returns zero if the deadline has + * expired or if the remaining interval rounds down to zero jiffies. + */ +static long +amdgpu_wait_event_deadline_to_jiffies(u64 deadline_ns) +{ + u64 now_ns; + + now_ns = ktime_get_ns(); + if (deadline_ns <= now_ns) + return 0; + + return nsecs_to_jiffies(deadline_ns - now_ns); +} + +/** + * amdgpu_wait_event_valid_type - validate a WAIT_EVENT event type + * @event_type: kernel-defined AMDGPU event type + * + * Return: + * True when @event_type is supported by the WAIT_EVENT UAPI. + */ +static bool amdgpu_wait_event_valid_type(u32 event_type) +{ + switch (event_type) { + case DRM_AMDGPU_EVENT_TYPE_USERQ_EOP: + case DRM_AMDGPU_EVENT_TYPE_QUEUE_RESET: + case DRM_AMDGPU_EVENT_TYPE_MEMORY_EXCEPTION: + case DRM_AMDGPU_EVENT_TYPE_SCRATCH: + case DRM_AMDGPU_EVENT_TYPE_GPU_RESET: + return true; + default: + return false; + } +} + +/** + * amdgpu_wait_event_record_free - release a pending event record + * @rec: record to release + * + * Drop the queue reference owned by the record and free the record. + */ +static void +amdgpu_wait_event_record_free(struct amdgpu_wait_event_record *rec) +{ + if (!rec) + return; + + amdgpu_userq_put(rec->queue); + kfree(rec); +} + +/** + * amdgpu_wait_event_match - test whether a record matches a wait request + * @args: WAIT_EVENT request + * @queue: resolved queue for a queue-scoped request, or NULL + * @rec: pending event record + * + * Queue-scoped records are matched using queue pointer equality. + * queue_id is used only at the UAPI boundary and as returned metadata. + * + * Return: + * True when @rec matches the requested event type and queue scope. + */ +static bool +amdgpu_wait_event_match(const struct drm_amdgpu_wait_event *args, + struct amdgpu_usermode_queue *queue, + const struct amdgpu_wait_event_record *rec) +{ + if (rec->data.event_type != args->event_type) + return false; + + /* + * Queue pointers are the internal matching key. queue_id is used + * only at the UAPI boundary and as returned event metadata. + */ + if (amdgpu_wait_event_type_is_queue_scoped(args->event_type)) + return rec->queue == queue; + + return !queue; +} + +/** + * amdgpu_wait_event_has_match - check for a matching pending record + * @mgr: per-file WAIT_EVENT manager + * @args: WAIT_EVENT request + * @queue: resolved queue for a queue-scoped request, or NULL + * + * This helper is used as the waitqueue condition. It does not remove the + * matching record. + * + * Return: + * True when a matching record is pending. + */ +static bool +amdgpu_wait_event_has_match(struct amdgpu_wait_event_mgr *mgr, + const struct drm_amdgpu_wait_event *args, + struct amdgpu_usermode_queue *queue) +{ + struct amdgpu_wait_event_record *rec; + unsigned long flags; + bool found = false; + + spin_lock_irqsave(&mgr->lock, flags); + list_for_each_entry(rec, &mgr->pending, node) { + if (amdgpu_wait_event_match(args, queue, rec)) { + found = true; + break; + } + } + spin_unlock_irqrestore(&mgr->lock, flags); + + return found; +} + +/** + * amdgpu_wait_event_pop_match - remove the first matching record + * @mgr: per-file WAIT_EVENT manager + * @args: WAIT_EVENT request + * @queue: resolved queue for a queue-scoped request, or NULL + * + * Remove and return the first pending record matching the requested event. + * Removal provides single-consumer delivery. + * + * Return: + * Matching record, or NULL when no matching record is pending. + */ +static struct amdgpu_wait_event_record * +amdgpu_wait_event_pop_match(struct amdgpu_wait_event_mgr *mgr, + const struct drm_amdgpu_wait_event *args, + struct amdgpu_usermode_queue *queue) +{ + struct amdgpu_wait_event_record *rec, *tmp, *found = NULL; + unsigned long flags; + + spin_lock_irqsave(&mgr->lock, flags); + list_for_each_entry_safe(rec, tmp, &mgr->pending, node) { + if (!amdgpu_wait_event_match(args, queue, rec)) + continue; + + list_del(&rec->node); + found = rec; + break; + } + spin_unlock_irqrestore(&mgr->lock, flags); + + return found; +} + +/** + * amdgpu_wait_event_get_queue - resolve the requested queue scope + * @fpriv: AMDGPU per-file private data + * @args: WAIT_EVENT request + * @queue: returned queue reference + * + * Validate the requested event type and resolve queue_id for queue-scoped + * events. Device-scoped events require queue_id to be zero. + * + * The caller owns the returned queue reference and must release it with + * amdgpu_userq_put(). + * + * Return: + * Zero on success or a negative error code. + */ +static int +amdgpu_wait_event_get_queue(struct amdgpu_fpriv *fpriv, + const struct drm_amdgpu_wait_event *args, + struct amdgpu_usermode_queue **queue) +{ + *queue = NULL; + + if (!amdgpu_wait_event_valid_type(args->event_type)) + return -EINVAL; + + if (amdgpu_wait_event_type_is_queue_scoped(args->event_type)) { + if (!args->queue_id) + return -EINVAL; + + *queue = amdgpu_userq_get(&fpriv->userq_mgr, args->queue_id); + if (!*queue) + return -ENOENT; + + return 0; + } + + if (args->queue_id) + return -EINVAL; + + return 0; +} + +/** + * amdgpu_wait_event_mgr_init - initialize a per-file WAIT_EVENT manager + * @mgr: manager to initialize + * + * Initialize the pending-record list, waitqueue, sequence counter and + * shutdown state. + */ +void amdgpu_wait_event_mgr_init(struct amdgpu_wait_event_mgr *mgr) +{ + spin_lock_init(&mgr->lock); + init_waitqueue_head(&mgr->wq); + INIT_LIST_HEAD(&mgr->pending); + atomic64_set(&mgr->seqno, 0); + mgr->dead = false; +} + +/** + * amdgpu_wait_event_mgr_fini - finalize a per-file WAIT_EVENT manager + * @mgr: manager to finalize + * + * Stop new records from being published, detach all pending records, + * release their queue references and wake blocked waiters. + * + * The manager is embedded in amdgpu_fpriv. The USERQ manager is torn down + * before drm_file postclose invokes this function. Queue teardown removes + * queues from producer lookup paths and drains queue work, so USERQ + * producers can no longer publish new WAIT_EVENT records before @mgr + * goes out of scope. + */ +void amdgpu_wait_event_mgr_fini(struct amdgpu_wait_event_mgr *mgr) +{ + struct amdgpu_wait_event_record *rec, *tmp; + unsigned long flags; + LIST_HEAD(removed); + + /* + * Prevent new records from being published before detaching pending + * records and waking blocked waiters. + */ + spin_lock_irqsave(&mgr->lock, flags); + mgr->dead = true; + list_splice_init(&mgr->pending, &removed); + spin_unlock_irqrestore(&mgr->lock, flags); + + list_for_each_entry_safe(rec, tmp, &removed, node) { + list_del(&rec->node); + amdgpu_wait_event_record_free(rec); + } + + wake_up_interruptible_all(&mgr->wq); +} + +/** + * amdgpu_wait_event_remove_queue - remove pending records for a queue + * @mgr: per-file WAIT_EVENT manager + * @queue: queue being removed + * + * Detach all pending records associated with @queue while holding the + * manager lock. Queue references are released after the lock is dropped. + */ +void amdgpu_wait_event_remove_queue(struct amdgpu_wait_event_mgr *mgr, + struct amdgpu_usermode_queue *queue) +{ + struct amdgpu_wait_event_record *rec, *tmp; + unsigned long flags; + LIST_HEAD(removed); + + if (!mgr || !queue) + return; + + spin_lock_irqsave(&mgr->lock, flags); + list_for_each_entry_safe(rec, tmp, &mgr->pending, node) { + if (rec->queue != queue) + continue; + + list_move_tail(&rec->node, &removed); + } + spin_unlock_irqrestore(&mgr->lock, flags); + + list_for_each_entry_safe(rec, tmp, &removed, node) { + list_del(&rec->node); + amdgpu_wait_event_record_free(rec); + } + + wake_up_interruptible_all(&mgr->wq); +} + +/** + * amdgpu_wait_event_drm_ioctl - wait for an AMDGPU render-node event + * @dev: DRM device + * @data: struct drm_amdgpu_wait_event request + * @file_priv: DRM file issuing the request + * + * Resolve the request scope, consume the first matching pending record and + * copy its metadata to userspace. + * + * deadline_ns is an absolute CLOCK_MONOTONIC deadline. The remaining wait + * interval is recomputed from the original deadline after every wakeup so + * that spurious wakeups cannot extend the requested deadline. + * + * Return: + * Zero on success or a negative error code. + */ +int amdgpu_wait_event_drm_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct amdgpu_fpriv *fpriv = file_priv->driver_priv; + struct drm_amdgpu_wait_event *args = data; + struct amdgpu_usermode_queue *queue = NULL; + struct amdgpu_wait_event_mgr *mgr; + struct amdgpu_wait_event_record *rec; + long remaining; + int ret; + + if (!fpriv) + return -EINVAL; + + if (args->flags || !args->event_type || !args->out_ptr) + return -EINVAL; + + if (args->out_size < sizeof(struct drm_amdgpu_wait_event_data)) + return -EINVAL; + + ret = amdgpu_wait_event_get_queue(fpriv, args, &queue); + if (ret) + return ret; + + mgr = &fpriv->wait_event_mgr; + + for (;;) { + rec = amdgpu_wait_event_pop_match(mgr, args, queue); + if (rec) + break; + + if (READ_ONCE(mgr->dead)) { + ret = -EIO; + goto out_put_queue; + } + + if (signal_pending(current)) { + ret = -ERESTARTSYS; + goto out_put_queue; + } + + remaining = amdgpu_wait_event_deadline_to_jiffies(args->deadline_ns); + if (!remaining) { + ret = -ETIME; + goto out_put_queue; + } + + remaining = wait_event_interruptible_timeout(mgr->wq, + READ_ONCE(mgr->dead) || + amdgpu_wait_event_has_match(mgr, args, queue), + remaining); + if (remaining < 0) { + ret = remaining; + goto out_put_queue; + } + } + + if (copy_to_user(u64_to_user_ptr(args->out_ptr), &rec->data, + sizeof(rec->data))) + ret = -EFAULT; + else + ret = 0; + + amdgpu_wait_event_record_free(rec); + +out_put_queue: + amdgpu_userq_put(queue); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h new file mode 100644 index 000000000000..9da68eb6c9b0 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __AMDGPU_WAIT_EVENT_H__ +#define __AMDGPU_WAIT_EVENT_H__ + +#include <linux/atomic.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/wait.h> + +#include <drm/drm_device.h> +#include <drm/drm_file.h> + +#include <uapi/drm/amdgpu_drm.h> + +struct amdgpu_usermode_queue; + +/** + * struct amdgpu_wait_event_record - pending WAIT_EVENT record + * @node: link in the manager's pending-record list + * @queue: referenced queue for queue-scoped events, or NULL + * @data: event metadata returned to userspace + */ +struct amdgpu_wait_event_record { + struct list_head node; + struct amdgpu_usermode_queue *queue; + struct drm_amdgpu_wait_event_data data; +}; + +/** + * struct amdgpu_wait_event_mgr - per-file WAIT_EVENT manager + * @lock: protects @pending and @dead + * @wq: waitqueue used by blocked WAIT_EVENT ioctls + * @pending: pending event records + * @seqno: per-file monotonically increasing event sequence number + * @dead: prevents new records from being queued during teardown + */ +struct amdgpu_wait_event_mgr { + /* Protects @pending and @dead. */ + spinlock_t lock; + wait_queue_head_t wq; + struct list_head pending; + atomic64_t seqno; + bool dead; +}; + +void amdgpu_wait_event_mgr_init(struct amdgpu_wait_event_mgr *mgr); +void amdgpu_wait_event_mgr_fini(struct amdgpu_wait_event_mgr *mgr); + +void amdgpu_wait_event_remove_queue(struct amdgpu_wait_event_mgr *mgr, + struct amdgpu_usermode_queue *queue); + +void amdgpu_wait_event_add(struct amdgpu_wait_event_mgr *mgr, + u32 event_type, + struct amdgpu_usermode_queue *queue); + +int amdgpu_wait_event_drm_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +/** + * amdgpu_wait_event_type_is_queue_scoped - test event queue scope + * @event_type: kernel-defined AMDGPU event type + * + * Return: + * True when @event_type requires a USERQ queue handle. + */ +static inline bool amdgpu_wait_event_type_is_queue_scoped(u32 event_type) +{ + switch (event_type) { + case DRM_AMDGPU_EVENT_TYPE_USERQ_EOP: + case DRM_AMDGPU_EVENT_TYPE_QUEUE_RESET: + case DRM_AMDGPU_EVENT_TYPE_SCRATCH: + return true; + default: + return false; + } +} + +#endif /* __AMDGPU_WAIT_EVENT_H__ */ -- 2.34.1
