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=UTF-8 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 | 119 ++++++++++++++++++----- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 5 +- 4 files changed, 107 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 411ee894f623..2c1a936459ac 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 7d4e07452cdb..464836f2a53f 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) { - int i; - char name[MAX_DEBUGFS_FILENAME_LEN]; 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; + + entry->process = p; + entry->pid = p->lead_thread->pid; + + 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; + } + + 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); - 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); + kfd_debugfs_create_pasid_files(p, entry->proc_dentry); - /* Create debugfs files for each GPU: - * - proc//pasid_ - */ - for (i = 0; i < p->n_pdds; i++) { - struct kfd_process_device *pdd = p->pdds[i]; + return 0; - 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); - } +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 a55f119ecf4c..88191a4c1657 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 da4257c9aae0..eb508fe3ded7 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); }