Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Kent Russell and committed by
Alex Deucher
de9f26bb e82fdb16

+113 -2
+6
drivers/gpu/drm/amd/amdkfd/kfd_module.c
··· 56 56 if (err < 0) 57 57 goto err_create_wq; 58 58 59 + /* Ignore the return value, so that we can continue 60 + * to init the KFD, even if procfs isn't craated 61 + */ 62 + kfd_procfs_init(); 63 + 59 64 kfd_debugfs_init(); 60 65 61 66 return 0; ··· 77 72 { 78 73 kfd_debugfs_fini(); 79 74 kfd_process_destroy_wq(); 75 + kfd_procfs_shutdown(); 80 76 kfd_topology_shutdown(); 81 77 kfd_chardev_exit(); 82 78 }
+9
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
··· 35 35 #include <linux/kfifo.h> 36 36 #include <linux/seq_file.h> 37 37 #include <linux/kref.h> 38 + #include <linux/sysfs.h> 38 39 #include <kgd_kfd_interface.h> 39 40 40 41 #include "amd_shared.h" ··· 719 718 * restored after an eviction 720 719 */ 721 720 unsigned long last_restore_timestamp; 721 + 722 + /* Kobj for our procfs */ 723 + struct kobject *kobj; 724 + struct attribute attr_pasid; 722 725 }; 723 726 724 727 #define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */ ··· 824 819 int kfd_gtt_sa_free(struct kfd_dev *kfd, struct kfd_mem_obj *mem_obj); 825 820 826 821 extern struct device *kfd_device; 822 + 823 + /* KFD's procfs */ 824 + void kfd_procfs_init(void); 825 + void kfd_procfs_shutdown(void); 827 826 828 827 /* Topology */ 829 828 int kfd_topology_init(void);
+98 -2
drivers/gpu/drm/amd/amdkfd/kfd_process.c
··· 68 68 static void evict_process_worker(struct work_struct *work); 69 69 static void restore_process_worker(struct work_struct *work); 70 70 71 + struct kfd_procfs_tree { 72 + struct kobject *kobj; 73 + }; 74 + 75 + static struct kfd_procfs_tree procfs; 76 + 77 + static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr, 78 + char *buffer) 79 + { 80 + int val = 0; 81 + 82 + if (strcmp(attr->name, "pasid") == 0) { 83 + struct kfd_process *p = container_of(attr, struct kfd_process, 84 + attr_pasid); 85 + val = p->pasid; 86 + } else { 87 + pr_err("Invalid attribute"); 88 + return -EINVAL; 89 + } 90 + 91 + return snprintf(buffer, PAGE_SIZE, "%d\n", val); 92 + } 93 + 94 + static void kfd_procfs_kobj_release(struct kobject *kobj) 95 + { 96 + kfree(kobj); 97 + } 98 + 99 + static const struct sysfs_ops kfd_procfs_ops = { 100 + .show = kfd_procfs_show, 101 + }; 102 + 103 + static struct kobj_type procfs_type = { 104 + .release = kfd_procfs_kobj_release, 105 + .sysfs_ops = &kfd_procfs_ops, 106 + }; 107 + 108 + void kfd_procfs_init(void) 109 + { 110 + int ret = 0; 111 + 112 + procfs.kobj = kfd_alloc_struct(procfs.kobj); 113 + if (!procfs.kobj) 114 + return; 115 + 116 + ret = kobject_init_and_add(procfs.kobj, &procfs_type, 117 + &kfd_device->kobj, "proc"); 118 + if (ret) { 119 + pr_warn("Could not create procfs proc folder"); 120 + /* If we fail to create the procfs, clean up */ 121 + kfd_procfs_shutdown(); 122 + } 123 + } 124 + 125 + void kfd_procfs_shutdown(void) 126 + { 127 + if (procfs.kobj) { 128 + kobject_del(procfs.kobj); 129 + kobject_put(procfs.kobj); 130 + procfs.kobj = NULL; 131 + } 132 + } 71 133 72 134 int kfd_process_create_wq(void) 73 135 { ··· 268 206 { 269 207 struct kfd_process *process; 270 208 struct task_struct *thread = current; 209 + int ret; 271 210 272 211 if (!thread->mm) 273 212 return ERR_PTR(-EINVAL); ··· 286 223 287 224 /* A prior open of /dev/kfd could have already created the process. */ 288 225 process = find_process(thread); 289 - if (process) 226 + if (process) { 290 227 pr_debug("Process already found\n"); 291 - else 228 + } else { 292 229 process = create_process(thread, filep); 293 230 231 + if (!procfs.kobj) 232 + goto out; 233 + 234 + process->kobj = kfd_alloc_struct(process->kobj); 235 + if (!process->kobj) { 236 + pr_warn("Creating procfs kobject failed"); 237 + goto out; 238 + } 239 + ret = kobject_init_and_add(process->kobj, &procfs_type, 240 + procfs.kobj, "%d", 241 + (int)process->lead_thread->pid); 242 + if (ret) { 243 + pr_warn("Creating procfs pid directory failed"); 244 + goto out; 245 + } 246 + 247 + process->attr_pasid.name = "pasid"; 248 + process->attr_pasid.mode = KFD_SYSFS_FILE_MODE; 249 + sysfs_attr_init(&process->attr_pasid); 250 + ret = sysfs_create_file(process->kobj, &process->attr_pasid); 251 + if (ret) 252 + pr_warn("Creating pasid for pid %d failed", 253 + (int)process->lead_thread->pid); 254 + } 255 + out: 294 256 mutex_unlock(&kfd_processes_mutex); 295 257 296 258 return process; ··· 442 354 { 443 355 struct kfd_process *p = container_of(work, struct kfd_process, 444 356 release_work); 357 + 358 + /* Remove the procfs files */ 359 + if (p->kobj) { 360 + sysfs_remove_file(p->kobj, &p->attr_pasid); 361 + kobject_del(p->kobj); 362 + kobject_put(p->kobj); 363 + p->kobj = NULL; 364 + } 445 365 446 366 kfd_iommu_unbind_process(p); 447 367