From f021a37211ef96887759be7fb6ee15cf1b6e5243 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 27 Feb 2018 18:32:17 -0500 Subject: [PATCH 3441/4131] drm/amdkfd: Add ioctl to acquire VM from a DRM FD If user mode doesn't use this ioctl before the first time kfd_bind_process_to_device is called, we still create our own VM to maintain backwards compatibility. Change-Id: I5c33bf32b597ccaba3eee5c6b1c90238913adaa5 Signed-off-by: Felix Kuehling --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 49 +++++++++++++++++++++++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 ++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 36 +++++++++++++++++++---- 3 files changed, 81 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 5c0ea45..01c8b19 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1151,6 +1151,50 @@ static int kfd_ioctl_get_tile_config(struct file *filep, return 0; } +static int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p, + void *data) +{ + struct kfd_ioctl_acquire_vm_args *args = data; + struct kfd_process_device *pdd; + struct kfd_dev *dev; + struct file *drm_file; + int ret; + + dev = kfd_device_by_id(args->gpu_id); + if (!dev) + return -EINVAL; + + drm_file = fget(args->drm_fd); + if (!drm_file) + return -EINVAL; + + mutex_lock(&p->mutex); + + pdd = kfd_get_process_device_data(dev, p); + if (!pdd) { + ret = -EINVAL; + goto err_unlock; + } + + if (pdd->drm_file) { + ret = pdd->drm_file == drm_file ? 0 : -EBUSY; + goto err_unlock; + } + + ret = kfd_process_device_init_vm(pdd, drm_file); + if (ret) + goto err_unlock; + /* On success, the PDD keeps the drm_file reference */ + mutex_unlock(&p->mutex); + + return 0; + +err_unlock: + mutex_unlock(&p->mutex); + fput(drm_file); + return ret; +} + bool kfd_dev_is_large_bar(struct kfd_dev *dev) { struct kfd_local_mem_info mem_info; @@ -2014,7 +2058,10 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { kfd_ioctl_cross_memory_copy, 0), AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_QUEUE_WAVE_STATE, - kfd_ioctl_get_queue_wave_state, 0) + kfd_ioctl_get_queue_wave_state, 0), + + AMDKFD_IOCTL_DEF(AMDKFD_IOC_ACQUIRE_VM, + kfd_ioctl_acquire_vm, 0) }; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 345224e..121be0c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -637,6 +637,7 @@ struct kfd_process_device { uint64_t scratch_limit; /* VM context for GPUVM allocations */ + struct file *drm_file; void *vm; /* GPUVM allocations storage */ @@ -766,6 +767,8 @@ void kfd_unref_process(struct kfd_process *p); void kfd_suspend_all_processes(void); int kfd_resume_all_processes(void); +int kfd_process_device_init_vm(struct kfd_process_device *pdd, + struct file *drm_file); struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev, struct kfd_process *p); struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 32f78fd..c627b63 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -340,7 +340,9 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) list_for_each_entry_safe(pdd, temp, &p->per_device_data, per_device_list) { /* Destroy the GPUVM VM context */ - if (pdd->vm) + if (pdd->drm_file) + fput(pdd->drm_file); + else if (pdd->vm) pdd->dev->kfd2kgd->destroy_process_vm( pdd->dev->kgd, pdd->vm); @@ -688,7 +690,22 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, return NULL; } -static int kfd_process_device_init_vm(struct kfd_process_device *pdd) +/** + * kfd_process_device_init_vm - Initialize a VM for a process-device + * + * @pdd: The process-device + * @drm_file: Optional pointer to a DRM file descriptor + * + * If @drm_file is specified, it will be used to acquire the VM from + * that file descriptor. If successful, the @pdd takes ownership of + * the file descriptor. + * + * If @drm_file is NULL, a new VM is created. + * + * Returns 0 on success, -errno on failure. + */ +int kfd_process_device_init_vm(struct kfd_process_device *pdd, + struct file *drm_file) { struct kfd_process *p; struct kfd_dev *dev; @@ -700,8 +717,12 @@ static int kfd_process_device_init_vm(struct kfd_process_device *pdd) p = pdd->process; dev = pdd->dev; - ret = dev->kfd2kgd->create_process_vm(dev->kgd, &pdd->vm, - &p->process_info, &p->ef); + if (drm_file) + ret = dev->kfd2kgd->acquire_process_vm( + dev->kgd, drm_file, &pdd->vm, &p->process_info, &p->ef); + else + ret = dev->kfd2kgd->create_process_vm( + dev->kgd, &pdd->vm, &p->process_info, &p->ef); if (ret) { pr_err("Failed to create process VM object\n"); return ret; @@ -714,12 +735,15 @@ static int kfd_process_device_init_vm(struct kfd_process_device *pdd) if (ret) goto err_init_cwsr; + pdd->drm_file = drm_file; + return 0; err_init_cwsr: err_reserve_ib_mem: kfd_process_device_free_bos(pdd); - dev->kfd2kgd->destroy_process_vm(dev->kgd, pdd->vm); + if (!drm_file) + dev->kfd2kgd->destroy_process_vm(dev->kgd, pdd->vm); pdd->vm = NULL; return ret; @@ -748,7 +772,7 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev, if (err) return ERR_PTR(err); - err = kfd_process_device_init_vm(pdd); + err = kfd_process_device_init_vm(pdd, NULL); if (err) return ERR_PTR(err); -- 2.7.4