This commit implemetns a new ioctl AMDKFD_IOC_CREATE_PROCESS that creates a new secondary kfd_progress on the FD.
To keep backward compatibility, userspace programs need to invoke this ioctl explicitly on a FD to create a secondary kfd_process which replacing its primary kfd_process. This commit bumps ioctl minor version. Signed-off-by: Zhu Lingshan <lingshan....@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 41 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 3 +- include/uapi/linux/kfd_ioctl.h | 8 +++-- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 662b181f1fd2..aeb5d4b31e9f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -3135,6 +3135,44 @@ static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, v return r; } +/* userspace programs need to invoke this ioctl explicitly on a FD to + * create a secondary kfd_process which replacing its primary kfd_process + */ +static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, void *data) +{ + struct kfd_process *process; + int ret; + + if (!filep->private_data || !p) + return -EINVAL; + + if (p != filep->private_data) + return -EINVAL; + + /* Each FD owns only one kfd_process */ + if (!p->primary) + return -EINVAL; + + mutex_lock(&kfd_processes_mutex); + process = create_process(current, false); + mutex_unlock(&kfd_processes_mutex); + + if (IS_ERR(process)) + return PTR_ERR(process); + + /* Each open() increases kref of the primary kfd_process, + * so we need to reduce it here before we create a new secondary process replacing it + */ + kfd_unref_process(p); + + filep->private_data = process; + ret = kfd_create_process_sysfs(process); + if (ret) + pr_warn("Failed to create sysfs entry for the kfd_process"); + + return 0; +} + #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ .cmd_drv = 0, .name = #ioctl} @@ -3253,6 +3291,9 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_TRAP, kfd_ioctl_set_debug_trap, 0), + + AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_PROCESS, + kfd_ioctl_create_process, 0), }; #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 25534473c28f..95c7292bdd02 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1053,6 +1053,7 @@ int kfd_create_process_sysfs(struct kfd_process *process); struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid, struct kfd_process_device **pdd); struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm); +struct kfd_process *create_process(const struct task_struct *thread, bool primary); int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id); int kfd_process_gpuid_from_node(struct kfd_process *p, struct kfd_node *node, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 0c3f0cc16bf4..f51e3f4aaf48 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -71,7 +71,6 @@ static struct workqueue_struct *kfd_restore_wq; static struct kfd_process *find_process(const struct task_struct *thread, bool ref); static void kfd_process_ref_release(struct kref *ref); -static struct kfd_process *create_process(const struct task_struct *thread, bool primary); static void evict_process_worker(struct work_struct *work); static void restore_process_worker(struct work_struct *work); @@ -1580,7 +1579,7 @@ void kfd_process_set_trap_debug_flag(struct qcm_process_device *qpd, * On return the kfd_process is fully operational and will be freed when the * mm is released */ -static struct kfd_process *create_process(const struct task_struct *thread, bool primary) +struct kfd_process *create_process(const struct task_struct *thread, bool primary) { struct kfd_process *process; struct mmu_notifier *mn; diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index 04c7d283dc7d..1d206ecc831e 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -44,9 +44,10 @@ * - 1.16 - Add contiguous VRAM allocation flag * - 1.17 - Add SDMA queue creation with target SDMA engine ID * - 1.18 - Rename pad in set_memory_policy_args to misc_process_flag + * - 1.19 - Add a new ioctl to craete secondary kfd processes */ #define KFD_IOCTL_MAJOR_VERSION 1 -#define KFD_IOCTL_MINOR_VERSION 18 +#define KFD_IOCTL_MINOR_VERSION 19 struct kfd_ioctl_get_version_args { __u32 major_version; /* from KFD */ @@ -1671,7 +1672,10 @@ struct kfd_ioctl_dbg_trap_args { #define AMDKFD_IOC_DBG_TRAP \ AMDKFD_IOWR(0x26, struct kfd_ioctl_dbg_trap_args) +#define AMDKFD_IOC_CREATE_PROCESS \ + AMDKFD_IO(0x27) + #define AMDKFD_COMMAND_START 0x01 -#define AMDKFD_COMMAND_END 0x27 +#define AMDKFD_COMMAND_END 0x28 #endif -- 2.47.1