drm/amdgpu: fix VM faults caused by vm_grab_id() v4
[linux-2.6-block.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_job.c
CommitLineData
c1b69ed0
CZ
1/*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 *
23 */
24#include <linux/kthread.h>
25#include <linux/wait.h>
26#include <linux/sched.h>
27#include <drm/drmP.h>
28#include "amdgpu.h"
7034decf 29#include "amdgpu_trace.h"
c1b69ed0 30
50838c8c
CK
31int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
32 struct amdgpu_job **job)
33{
34 size_t size = sizeof(struct amdgpu_job);
35
36 if (num_ibs == 0)
37 return -EINVAL;
38
39 size += sizeof(struct amdgpu_ib) * num_ibs;
40
41 *job = kzalloc(size, GFP_KERNEL);
42 if (!*job)
43 return -ENOMEM;
44
45 (*job)->adev = adev;
46 (*job)->ibs = (void *)&(*job)[1];
47 (*job)->num_ibs = num_ibs;
50838c8c 48
e86f9cee
CK
49 amdgpu_sync_create(&(*job)->sync);
50
50838c8c
CK
51 return 0;
52}
53
d71518b5
CK
54int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size,
55 struct amdgpu_job **job)
56{
57 int r;
58
59 r = amdgpu_job_alloc(adev, 1, job);
60 if (r)
61 return r;
62
63 r = amdgpu_ib_get(adev, NULL, size, &(*job)->ibs[0]);
64 if (r)
65 kfree(*job);
66
67 return r;
68}
69
50838c8c
CK
70void amdgpu_job_free(struct amdgpu_job *job)
71{
72 unsigned i;
73
74 for (i = 0; i < job->num_ibs; ++i)
75 amdgpu_ib_free(job->adev, &job->ibs[i]);
76
77 amdgpu_bo_unref(&job->uf.bo);
e86f9cee 78 amdgpu_sync_free(&job->sync);
d71518b5
CK
79 kfree(job);
80}
81
82int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
2bd9ccfa
CK
83 struct amd_sched_entity *entity, void *owner,
84 struct fence **f)
d71518b5 85{
d71518b5
CK
86 job->ring = ring;
87 job->base.sched = &ring->sched;
2bd9ccfa 88 job->base.s_entity = entity;
d71518b5
CK
89 job->base.s_fence = amd_sched_fence_create(job->base.s_entity, owner);
90 if (!job->base.s_fence)
91 return -ENOMEM;
92
93 *f = fence_get(&job->base.s_fence->base);
94
95 job->owner = owner;
96 amd_sched_entity_push_job(&job->base);
97
98 return 0;
50838c8c
CK
99}
100
0856cab1 101static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
e61235db 102{
a6db8a33 103 struct amdgpu_job *job = to_amdgpu_job(sched_job);
8d0a7cea
CK
104 struct amdgpu_vm *vm = job->ibs->vm;
105
e86f9cee 106 struct fence *fence = amdgpu_sync_get_fence(&job->sync);
8d0a7cea 107
4ff37a83 108 if (fence == NULL && vm && !job->ibs->vm_id) {
b07c60c0 109 struct amdgpu_ring *ring = job->ring;
4ff37a83
CK
110 unsigned i, vm_id;
111 uint64_t vm_pd_addr;
8d0a7cea
CK
112 int r;
113
e86f9cee 114 r = amdgpu_vm_grab_id(vm, ring, &job->sync,
4ff37a83
CK
115 &job->base.s_fence->base,
116 &vm_id, &vm_pd_addr);
94dd0a4a 117 if (r)
8d0a7cea 118 DRM_ERROR("Error getting VM ID (%d)\n", r);
4ff37a83
CK
119 else {
120 for (i = 0; i < job->num_ibs; ++i) {
121 job->ibs[i].vm_id = vm_id;
122 job->ibs[i].vm_pd_addr = vm_pd_addr;
123 }
124 }
8d0a7cea 125
e86f9cee 126 fence = amdgpu_sync_get_fence(&job->sync);
8d0a7cea
CK
127 }
128
129 return fence;
e61235db
CK
130}
131
0856cab1 132static struct fence *amdgpu_job_run(struct amd_sched_job *sched_job)
c1b69ed0 133{
ec72b800 134 struct fence *fence = NULL;
4c7eb91c 135 struct amdgpu_job *job;
bd755d08 136 int r;
c1b69ed0 137
4c7eb91c 138 if (!sched_job) {
4cef9267 139 DRM_ERROR("job is null\n");
6f0e54a9 140 return NULL;
4cef9267 141 }
a6db8a33 142 job = to_amdgpu_job(sched_job);
e86f9cee
CK
143
144 r = amdgpu_sync_wait(&job->sync);
145 if (r) {
146 DRM_ERROR("failed to sync wait (%d)\n", r);
147 return NULL;
148 }
149
7034decf 150 trace_amdgpu_sched_run_job(job);
e86f9cee
CK
151 r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs, job->owner,
152 job->sync.last_vm_update, &fence);
1886d1a9
CK
153 if (r) {
154 DRM_ERROR("Error scheduling IBs (%d)\n", r);
c1b69ed0 155 goto err;
1886d1a9
CK
156 }
157
1886d1a9 158err:
d71518b5 159 amdgpu_job_free(job);
ec72b800 160 return fence;
c1b69ed0
CZ
161}
162
163struct amd_sched_backend_ops amdgpu_sched_ops = {
0856cab1
CK
164 .dependency = amdgpu_job_dependency,
165 .run_job = amdgpu_job_run,
c1b69ed0 166};