From 325de6bf3328efd5acf5072337fc196928753de8 Mon Sep 17 00:00:00 2001 From: Zhu Lingshan Date: Wed, 1 Jul 2026 11:03:09 +0800 Subject: [PATCH] drm/amdkfd: expose pasid of secondary contexts by debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Current kfd debugfs interfaces only expose pasid of the primary process, this commit exposes pasid of secondary contexts by debugfs Just like entries under sysfs, the secondary contexts are named as context_ under its primary kfd process. The layout: /sys/kernel/debug/kfd/proc# tree . └── 5802 ├── context_0 │   ├── pasid_1025 │   └── pasid_63266 ├── context_1 │   ├── pasid_1025 │   └── pasid_63266 ├── pasid_1025 └── pasid_63266 Another fix is, kfd_debugfs_add_process may fail, this commit change it to return a meaningful value other than void Signed-off-by: Zhu Lingshan Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 5 + drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c | 113 +++++++++++++++++++---- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 5 +- 4 files changed, 104 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 411ee894f623d..2c1a936459ac8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -3303,6 +3303,11 @@ static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, v } filep->private_data = process; + ret = kfd_debugfs_add_process(process); + if (ret) + pr_warn("Failed to create debugfs entry for the kfd_process, ret = %d\n", + ret); + mutex_unlock(&kfd_processes_mutex); ret = kfd_create_process_sysfs(process); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c b/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c index 7d4e07452cdbc..464836f2a53f9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c @@ -33,6 +33,7 @@ static struct list_head procs; struct debugfs_proc_entry { struct list_head list; struct dentry *proc_dentry; + struct kfd_process *process; pid_t pid; }; @@ -140,34 +141,97 @@ static const struct file_operations kfd_debugfs_pasid_fops = { .read = kfd_debugfs_pasid_read, }; -void kfd_debugfs_add_process(struct kfd_process *p) +/* This helper locates the debugfs entry of a kfd process */ +static struct debugfs_proc_entry *kfd_debugfs_find_process_entry(struct kfd_process *p) { + struct debugfs_proc_entry *entry; + + list_for_each_entry(entry, &procs, list) { + if (entry->process == p) + return entry; + } + + return NULL; +} + +/* This helper creates pasid file of a kfd process under debugfs */ +static void kfd_debugfs_create_pasid_files(struct kfd_process *p, + struct dentry *dir) +{ + char name[MAX_DEBUGFS_FILENAME_LEN]; + struct kfd_process_device *pdd; int i; + + /* create pasid file for each GPU */ + for (i = 0; i < p->n_pdds; i++) { + pdd = p->pdds[i]; + snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "pasid_%u", pdd->dev->id); + debugfs_create_file((const char *)name, S_IFREG | 0444, + dir, pdd, &kfd_debugfs_pasid_fops); + } +} + +int kfd_debugfs_add_process(struct kfd_process *p) +{ + struct debugfs_proc_entry *primary_entry; char name[MAX_DEBUGFS_FILENAME_LEN]; + struct kfd_process *primary_process; struct debugfs_proc_entry *entry; + int ret; entry = kzalloc_obj(*entry); if (!entry) - return; + return -ENOMEM; - list_add(&entry->list, &procs); + entry->process = p; entry->pid = p->lead_thread->pid; - snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "%d", - (int)entry->pid); - entry->proc_dentry = debugfs_create_dir(name, debugfs_proc); - /* Create debugfs files for each GPU: - * - proc//pasid_ - */ - for (i = 0; i < p->n_pdds; i++) { - struct kfd_process_device *pdd = p->pdds[i]; + if (p->context_id == KFD_CONTEXT_ID_PRIMARY) { + snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "%d", + (int)entry->pid); + entry->proc_dentry = debugfs_create_dir(name, debugfs_proc); + } else { + primary_process = kfd_lookup_process_by_mm(p->lead_thread->mm); + if (!primary_process) { + ret = -ESRCH; + goto err_free_entry; + } - snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "pasid_%u", - pdd->dev->id); - debugfs_create_file((const char *)name, S_IFREG | 0444, - entry->proc_dentry, pdd, - &kfd_debugfs_pasid_fops); + primary_entry = kfd_debugfs_find_process_entry(primary_process); + kfd_unref_process(primary_process); + if (!primary_entry) { + pr_warn("Failed to find the primary debugfs entry for pid %d\n", + entry->pid); + ret = -ENOENT; + goto err_free_entry; + } + + snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "context_%u", + p->context_id); + entry->proc_dentry = debugfs_create_dir(name, + primary_entry->proc_dentry); } + if (IS_ERR_OR_NULL(entry->proc_dentry)) { + ret = entry->proc_dentry ? PTR_ERR(entry->proc_dentry) : -ENOMEM; + goto err_free_entry; + } + + list_add(&entry->list, &procs); + kfd_debugfs_create_pasid_files(p, entry->proc_dentry); + + return 0; + +err_free_entry: + kfree(entry); + return ret; +} + +/* This helper removes a debugfs entry and its sub-entries */ +static void kfd_debugfs_remove_entry(struct debugfs_proc_entry *entry) +{ + debugfs_remove(entry->proc_dentry); + list_del(&entry->list); + kfree(entry); } void kfd_debugfs_remove_process(struct kfd_process *p) @@ -175,13 +239,22 @@ void kfd_debugfs_remove_process(struct kfd_process *p) struct debugfs_proc_entry *entry, *next; mutex_lock(&kfd_processes_mutex); + if (p->context_id == KFD_CONTEXT_ID_PRIMARY) { + /* remove entries of secondary contexts */ + list_for_each_entry_safe(entry, next, &procs, list) { + if (entry->pid != p->lead_thread->pid || entry->process == p) + continue; + + kfd_debugfs_remove_entry(entry); + } + } + list_for_each_entry_safe(entry, next, &procs, list) { - if (entry->pid != p->lead_thread->pid) + if (entry->process != p) continue; - debugfs_remove_recursive(entry->proc_dentry); - list_del(&entry->list); - kfree(entry); + kfd_debugfs_remove_entry(entry); } + mutex_unlock(&kfd_processes_mutex); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a55f119ecf4cb..88191a4c16579 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1651,14 +1651,14 @@ int kfd_debugfs_hang_hws(struct kfd_node *dev); int pm_debugfs_hang_hws(struct packet_manager *pm); int dqm_debugfs_hang_hws(struct device_queue_manager *dqm); -void kfd_debugfs_add_process(struct kfd_process *p); +int kfd_debugfs_add_process(struct kfd_process *p); void kfd_debugfs_remove_process(struct kfd_process *p); #else static inline void kfd_debugfs_init(void) {} static inline void kfd_debugfs_fini(void) {} -static inline void kfd_debugfs_add_process(struct kfd_process *p) {} +static inline int kfd_debugfs_add_process(struct kfd_process *p) { return 0; } static inline void kfd_debugfs_remove_process(struct kfd_process *p) {} #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index da4257c9aae08..eb508fe3ded78 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1013,7 +1013,10 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) if (ret) pr_warn("Failed to create sysfs entry for the kfd_process"); - kfd_debugfs_add_process(process); + ret = kfd_debugfs_add_process(process); + if (ret) + pr_warn("Failed to create debugfs entry for the kfd_process, ret = %d\n", + ret); init_waitqueue_head(&process->wait_irq_drain); } -- 2.53.0