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