drm/amdkfd: Add procfs-style information for KFD processes
Add a folder structure to /sys/class/kfd/kfd/ called proc which contains subfolders, each representing an active KFD process' PID, containing 1 file: pasid. Signed-off-by: Kent Russell <kent.russell@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
e82fdb16a0
commit
de9f26bbd3
|
@ -56,6 +56,11 @@ static int kfd_init(void)
|
|||
if (err < 0)
|
||||
goto err_create_wq;
|
||||
|
||||
/* Ignore the return value, so that we can continue
|
||||
* to init the KFD, even if procfs isn't craated
|
||||
*/
|
||||
kfd_procfs_init();
|
||||
|
||||
kfd_debugfs_init();
|
||||
|
||||
return 0;
|
||||
|
@ -72,6 +77,7 @@ static void kfd_exit(void)
|
|||
{
|
||||
kfd_debugfs_fini();
|
||||
kfd_process_destroy_wq();
|
||||
kfd_procfs_shutdown();
|
||||
kfd_topology_shutdown();
|
||||
kfd_chardev_exit();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/kfifo.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <kgd_kfd_interface.h>
|
||||
|
||||
#include "amd_shared.h"
|
||||
|
@ -718,6 +719,10 @@ struct kfd_process {
|
|||
* restored after an eviction
|
||||
*/
|
||||
unsigned long last_restore_timestamp;
|
||||
|
||||
/* Kobj for our procfs */
|
||||
struct kobject *kobj;
|
||||
struct attribute attr_pasid;
|
||||
};
|
||||
|
||||
#define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */
|
||||
|
@ -820,6 +825,10 @@ int kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj);
|
|||
|
||||
extern struct device *kfd_device;
|
||||
|
||||
/* KFD's procfs */
|
||||
void kfd_procfs_init(void);
|
||||
void kfd_procfs_shutdown(void);
|
||||
|
||||
/* Topology */
|
||||
int kfd_topology_init(void);
|
||||
void kfd_topology_shutdown(void);
|
||||
|
|
|
@ -68,6 +68,68 @@ static struct kfd_process *create_process(const struct task_struct *thread,
|
|||
static void evict_process_worker(struct work_struct *work);
|
||||
static void restore_process_worker(struct work_struct *work);
|
||||
|
||||
struct kfd_procfs_tree {
|
||||
struct kobject *kobj;
|
||||
};
|
||||
|
||||
static struct kfd_procfs_tree procfs;
|
||||
|
||||
static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buffer)
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
if (strcmp(attr->name, "pasid") == 0) {
|
||||
struct kfd_process *p = container_of(attr, struct kfd_process,
|
||||
attr_pasid);
|
||||
val = p->pasid;
|
||||
} else {
|
||||
pr_err("Invalid attribute");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snprintf(buffer, PAGE_SIZE, "%d\n", val);
|
||||
}
|
||||
|
||||
static void kfd_procfs_kobj_release(struct kobject *kobj)
|
||||
{
|
||||
kfree(kobj);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops kfd_procfs_ops = {
|
||||
.show = kfd_procfs_show,
|
||||
};
|
||||
|
||||
static struct kobj_type procfs_type = {
|
||||
.release = kfd_procfs_kobj_release,
|
||||
.sysfs_ops = &kfd_procfs_ops,
|
||||
};
|
||||
|
||||
void kfd_procfs_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
procfs.kobj = kfd_alloc_struct(procfs.kobj);
|
||||
if (!procfs.kobj)
|
||||
return;
|
||||
|
||||
ret = kobject_init_and_add(procfs.kobj, &procfs_type,
|
||||
&kfd_device->kobj, "proc");
|
||||
if (ret) {
|
||||
pr_warn("Could not create procfs proc folder");
|
||||
/* If we fail to create the procfs, clean up */
|
||||
kfd_procfs_shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void kfd_procfs_shutdown(void)
|
||||
{
|
||||
if (procfs.kobj) {
|
||||
kobject_del(procfs.kobj);
|
||||
kobject_put(procfs.kobj);
|
||||
procfs.kobj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int kfd_process_create_wq(void)
|
||||
{
|
||||
|
@ -206,6 +268,7 @@ struct kfd_process *kfd_create_process(struct file *filep)
|
|||
{
|
||||
struct kfd_process *process;
|
||||
struct task_struct *thread = current;
|
||||
int ret;
|
||||
|
||||
if (!thread->mm)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
@ -223,11 +286,36 @@ struct kfd_process *kfd_create_process(struct file *filep)
|
|||
|
||||
/* A prior open of /dev/kfd could have already created the process. */
|
||||
process = find_process(thread);
|
||||
if (process)
|
||||
if (process) {
|
||||
pr_debug("Process already found\n");
|
||||
else
|
||||
} else {
|
||||
process = create_process(thread, filep);
|
||||
|
||||
if (!procfs.kobj)
|
||||
goto out;
|
||||
|
||||
process->kobj = kfd_alloc_struct(process->kobj);
|
||||
if (!process->kobj) {
|
||||
pr_warn("Creating procfs kobject failed");
|
||||
goto out;
|
||||
}
|
||||
ret = kobject_init_and_add(process->kobj, &procfs_type,
|
||||
procfs.kobj, "%d",
|
||||
(int)process->lead_thread->pid);
|
||||
if (ret) {
|
||||
pr_warn("Creating procfs pid directory failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
process->attr_pasid.name = "pasid";
|
||||
process->attr_pasid.mode = KFD_SYSFS_FILE_MODE;
|
||||
sysfs_attr_init(&process->attr_pasid);
|
||||
ret = sysfs_create_file(process->kobj, &process->attr_pasid);
|
||||
if (ret)
|
||||
pr_warn("Creating pasid for pid %d failed",
|
||||
(int)process->lead_thread->pid);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&kfd_processes_mutex);
|
||||
|
||||
return process;
|
||||
|
@ -355,6 +443,14 @@ static void kfd_process_wq_release(struct work_struct *work)
|
|||
struct kfd_process *p = container_of(work, struct kfd_process,
|
||||
release_work);
|
||||
|
||||
/* Remove the procfs files */
|
||||
if (p->kobj) {
|
||||
sysfs_remove_file(p->kobj, &p->attr_pasid);
|
||||
kobject_del(p->kobj);
|
||||
kobject_put(p->kobj);
|
||||
p->kobj = NULL;
|
||||
}
|
||||
|
||||
kfd_iommu_unbind_process(p);
|
||||
|
||||
kfd_process_free_outstanding_kfd_bos(p);
|
||||
|
|
Loading…
Reference in New Issue