mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 11:41:29 -04:00
drm/amdkfd: expose pasid of secondary contexts by debugfs
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 <lingshan.zhu@amd.com>
Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
c936b8126b
commit
325de6bf33
@@ -3303,6 +3303,11 @@ static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
filep->private_data = process;
|
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);
|
mutex_unlock(&kfd_processes_mutex);
|
||||||
|
|
||||||
ret = kfd_create_process_sysfs(process);
|
ret = kfd_create_process_sysfs(process);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ static struct list_head procs;
|
|||||||
struct debugfs_proc_entry {
|
struct debugfs_proc_entry {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct dentry *proc_dentry;
|
struct dentry *proc_dentry;
|
||||||
|
struct kfd_process *process;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -140,34 +141,97 @@ static const struct file_operations kfd_debugfs_pasid_fops = {
|
|||||||
.read = kfd_debugfs_pasid_read,
|
.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;
|
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);
|
entry = kzalloc_obj(*entry);
|
||||||
if (!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);
|
list_add(&entry->list, &procs);
|
||||||
entry->pid = p->lead_thread->pid;
|
kfd_debugfs_create_pasid_files(p, entry->proc_dentry);
|
||||||
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:
|
return 0;
|
||||||
* - proc/<pid>/pasid_<gpuid>
|
|
||||||
*/
|
|
||||||
for (i = 0; i < p->n_pdds; i++) {
|
|
||||||
struct kfd_process_device *pdd = p->pdds[i];
|
|
||||||
|
|
||||||
snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "pasid_%u",
|
err_free_entry:
|
||||||
pdd->dev->id);
|
kfree(entry);
|
||||||
debugfs_create_file((const char *)name, S_IFREG | 0444,
|
return ret;
|
||||||
entry->proc_dentry, pdd,
|
}
|
||||||
&kfd_debugfs_pasid_fops);
|
|
||||||
}
|
/* 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)
|
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;
|
struct debugfs_proc_entry *entry, *next;
|
||||||
|
|
||||||
mutex_lock(&kfd_processes_mutex);
|
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) {
|
list_for_each_entry_safe(entry, next, &procs, list) {
|
||||||
if (entry->pid != p->lead_thread->pid)
|
if (entry->process != p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
debugfs_remove_recursive(entry->proc_dentry);
|
kfd_debugfs_remove_entry(entry);
|
||||||
list_del(&entry->list);
|
|
||||||
kfree(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&kfd_processes_mutex);
|
mutex_unlock(&kfd_processes_mutex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1651,14 +1651,14 @@ int kfd_debugfs_hang_hws(struct kfd_node *dev);
|
|||||||
int pm_debugfs_hang_hws(struct packet_manager *pm);
|
int pm_debugfs_hang_hws(struct packet_manager *pm);
|
||||||
int dqm_debugfs_hang_hws(struct device_queue_manager *dqm);
|
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);
|
void kfd_debugfs_remove_process(struct kfd_process *p);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline void kfd_debugfs_init(void) {}
|
static inline void kfd_debugfs_init(void) {}
|
||||||
static inline void kfd_debugfs_fini(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) {}
|
static inline void kfd_debugfs_remove_process(struct kfd_process *p) {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1013,7 +1013,10 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
|
|||||||
if (ret)
|
if (ret)
|
||||||
pr_warn("Failed to create sysfs entry for the kfd_process");
|
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);
|
init_waitqueue_head(&process->wait_irq_drain);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user