summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
diff options
context:
space:
mode:
authorFelix Kuehling2018-03-15 22:27:52 +0100
committerOded Gabbay2018-03-15 22:27:52 +0100
commit0fc8011f89feb8b2c3008583b777d097e1974660 (patch)
tree77c0a44e6e9cefad545fc45141680b3b3b1dc7e1 /drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
parentdrm/amdkfd: Add ioctls for GPUVM memory management (diff)
downloadkernel-qcow2-linux-0fc8011f89feb8b2c3008583b777d097e1974660.tar.gz
kernel-qcow2-linux-0fc8011f89feb8b2c3008583b777d097e1974660.tar.xz
kernel-qcow2-linux-0fc8011f89feb8b2c3008583b777d097e1974660.zip
drm/amdkfd: Kmap event page for dGPUs
The events page must be accessible in user mode by the GPU and CPU as well as in kernel mode by the CPU. On dGPUs user mode virtual addresses are managed by the Thunk's GPU memory allocation code. Therefore we can't allocate the memory in kernel mode like we do on APUs. But KFD still needs to map the memory for kernel access. To facilitate this, the Thunk provides the buffer handle of the events page to KFD when creating the first event. Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd/kfd_chardev.c')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index a563ff2ca7dd..ec0b2c0284ec 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -923,6 +923,58 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
struct kfd_ioctl_create_event_args *args = data;
int err;
+ /* For dGPUs the event page is allocated in user mode. The
+ * handle is passed to KFD with the first call to this IOCTL
+ * through the event_page_offset field.
+ */
+ if (args->event_page_offset) {
+ struct kfd_dev *kfd;
+ struct kfd_process_device *pdd;
+ void *mem, *kern_addr;
+ uint64_t size;
+
+ if (p->signal_page) {
+ pr_err("Event page is already set\n");
+ return -EINVAL;
+ }
+
+ kfd = kfd_device_by_id(GET_GPU_ID(args->event_page_offset));
+ if (!kfd) {
+ pr_err("Getting device by id failed in %s\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&p->mutex);
+ pdd = kfd_bind_process_to_device(kfd, p);
+ if (IS_ERR(pdd)) {
+ err = PTR_ERR(pdd);
+ goto out_unlock;
+ }
+
+ mem = kfd_process_device_translate_handle(pdd,
+ GET_IDR_HANDLE(args->event_page_offset));
+ if (!mem) {
+ pr_err("Can't find BO, offset is 0x%llx\n",
+ args->event_page_offset);
+ err = -EINVAL;
+ goto out_unlock;
+ }
+ mutex_unlock(&p->mutex);
+
+ err = kfd->kfd2kgd->map_gtt_bo_to_kernel(kfd->kgd,
+ mem, &kern_addr, &size);
+ if (err) {
+ pr_err("Failed to map event page to kernel\n");
+ return err;
+ }
+
+ err = kfd_event_page_set(p, kern_addr, size);
+ if (err) {
+ pr_err("Failed to set event page\n");
+ return err;
+ }
+ }
+
err = kfd_event_create(filp, p, args->event_type,
args->auto_reset != 0, args->node_id,
&args->event_id, &args->event_trigger_data,
@@ -930,6 +982,10 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
&args->event_slot_index);
return err;
+
+out_unlock:
+ mutex_unlock(&p->mutex);
+ return err;
}
static int kfd_ioctl_destroy_event(struct file *filp, struct kfd_process *p,