From 5d9cdfc28fe5fc636d1c0d4086ba871d46992d17 Mon Sep 17 00:00:00 2001 From: Kent Russell Date: Thu, 13 Jun 2019 09:55:40 -0400 Subject: [PATCH 2801/2940] drm/amdkfd: Add procfs-style information for KFD processes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. Change-Id: Id3dfab8a6250264434b34ccddbcdb459d1da7478 Signed-off-by: Kent Russell Reviewed-by: Felix Kuehling Acked-by: Christian König --- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 6 ++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 10 +++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 100 ++++++++++++++++++++++- 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c index 81cde3a34c14..e0ce8f31efb8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c @@ -105,6 +105,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_init_peer_direct(); kfd_debugfs_init(); @@ -125,6 +130,7 @@ static void kfd_exit(void) kfd_debugfs_fini(); kfd_close_peer_direct(); kfd_process_destroy_wq(); + kfd_procfs_shutdown(); kfd_topology_shutdown(); kfd_chardev_exit(); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 964f8c20cea3..2bb74312b15b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -851,6 +852,11 @@ struct kfd_process { * restored after an eviction */ unsigned long last_restore_timestamp; + + /* Kobj for our procfs */ + struct kobject *kobj; + struct attribute attr_pasid; + unsigned long last_evict_timestamp; }; @@ -967,6 +973,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); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 6da0f3d8f3e9..b391f9406273 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -72,6 +72,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) { @@ -218,6 +280,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); @@ -235,11 +298,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, false); - 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; @@ -394,6 +482,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); -- 2.17.1