Add a global PASID->amdgpu_fpriv registry. This enables a later bridge entry point (called by KFD with just PASID+event_id) to find the render-node drm_file(s) for that PASID and signal any registered eventfd.
The registry supports multiple fpriv entries per PASID, since a process may open multiple render nodes / files. Cc: Harish Kasiviswanathan <[email protected]> Cc: Felix Kuehling <[email protected]> Cc: Alex Deucher <[email protected]> Cc: Christian König <[email protected]> Signed-off-by: Srinivasan Shanmugam <[email protected]> --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 + .../gpu/drm/amd/amdgpu/amdgpu_eventfd_pasid.c | 114 ++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd_pasid.c diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 8e22882b66aa..0a5ed8984ada 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -67,7 +67,8 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \ amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o amdgpu_dev_coredump.o \ - amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o + amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o \ + amdgpu_eventfd_pasid.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 b0e9b7ff2f80..4faf908d5af5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -477,6 +477,10 @@ void amdgpu_eventfd_signal(struct amdgpu_fpriv *fpriv, u32 event_id, u64 count); int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv); +/* Global PASID->fpriv registry for KFD->render eventfd bridge */ +void amdgpu_eventfd_pasid_register(struct amdgpu_fpriv *fpriv, u32 pasid); +void amdgpu_eventfd_pasid_unregister(struct amdgpu_fpriv *fpriv, u32 pasid); + /* * Writeback */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd_pasid.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd_pasid.c new file mode 100644 index 000000000000..770ccc0be70b --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd_pasid.c @@ -0,0 +1,114 @@ +/* + * 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/hashtable.h> +#include <linux/rcupdate.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include "amdgpu.h" + +/* + * Global PASID->fpriv registry used to bridge KFD event signaling to + * render-node eventfd subscribers. + */ + +#include <linux/hashtable.h> +#include <linux/rcupdate.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include "amdgpu.h" + +struct amdgpu_pasid_fpriv_node { + struct hlist_node hnode; + struct rcu_head rcu; + struct amdgpu_fpriv *fpriv; + u32 pasid; +}; + +#define AMDGPU_PASID_HT_BITS 8 /* 256 buckets */ +static DEFINE_HASHTABLE(amdgpu_pasid_ht, AMDGPU_PASID_HT_BITS); +static DEFINE_SPINLOCK(amdgpu_pasid_ht_lock); + +static void amdgpu_pasid_fpriv_node_free_rcu(struct rcu_head *rcu) +{ + struct amdgpu_pasid_fpriv_node *n = + container_of(rcu, struct amdgpu_pasid_fpriv_node, rcu); + kfree(n); +} + +static bool amdgpu_pasid_fpriv_registered_locked(struct amdgpu_fpriv *fpriv, u32 pasid) +{ + struct amdgpu_pasid_fpriv_node *n; + + hash_for_each_possible(amdgpu_pasid_ht, n, hnode, pasid) { + if (n->pasid == pasid && n->fpriv == fpriv) + return true; + } + return false; +} + +void amdgpu_eventfd_pasid_register(struct amdgpu_fpriv *fpriv, u32 pasid) +{ + struct amdgpu_pasid_fpriv_node *n; + + if (!fpriv || !pasid) + return; + + n = kzalloc(sizeof(*n), GFP_KERNEL); + if (!n) + return; + + n->fpriv = fpriv; + n->pasid = pasid; + + spin_lock(&amdgpu_pasid_ht_lock); + if (amdgpu_pasid_fpriv_registered_locked(fpriv, pasid)) { + spin_unlock(&amdgpu_pasid_ht_lock); + kfree(n); + return; + } + hash_add_rcu(amdgpu_pasid_ht, &n->hnode, pasid); + spin_unlock(&amdgpu_pasid_ht_lock); +} +EXPORT_SYMBOL_GPL(amdgpu_eventfd_pasid_register); + +void amdgpu_eventfd_pasid_unregister(struct amdgpu_fpriv *fpriv, u32 pasid) +{ + struct amdgpu_pasid_fpriv_node *n; + struct hlist_node *tmp; + + if (!fpriv || !pasid) + return; + + spin_lock(&amdgpu_pasid_ht_lock); + hash_for_each_possible_safe(amdgpu_pasid_ht, n, tmp, hnode, pasid) { + if (n->pasid == pasid && n->fpriv == fpriv) { + hash_del_rcu(&n->hnode); + call_rcu(&n->rcu, amdgpu_pasid_fpriv_node_free_rcu); + } + } + spin_unlock(&amdgpu_pasid_ht_lock); +} +EXPORT_SYMBOL_GPL(amdgpu_eventfd_pasid_unregister); -- 2.34.1
