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_<id> 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 <[email protected]>
---
 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 ab9e53dc8deb..2635218188cc 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 9bde2c64540f..02673f01b448 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(sizeof(*entry), GFP_KERNEL);
        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/<pid>/pasid_<gpuid>
-        */
-       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 ad4897f094a2..365c6289b05d 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -1649,14 +1649,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 8e701dcda8ec..a87878aee0f1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -1002,7 +1002,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

Reply via email to