Skip to content

Instantly share code, notes, and snippets.

@FurretUber
Created September 11, 2018 20:32
Show Gist options
  • Save FurretUber/1dd834e7c5d04ea06dccdffe9e377600 to your computer and use it in GitHub Desktop.
Save FurretUber/1dd834e7c5d04ea06dccdffe9e377600 to your computer and use it in GitHub Desktop.
Which lines?
<i915_gem_do_execbuffer@/home/usuario/Downloads/linux-4.17.18/drivers/gpu/drm/i915/i915_gem_execbuffer.c:0>
0 i915_gem_do_execbuffer(struct drm_device *dev,
struct drm_file *file,
struct drm_i915_gem_execbuffer2 *args,
struct drm_i915_gem_exec_object2 *exec,
struct drm_syncobj **fences)
5 {
struct i915_execbuffer eb;
7 struct dma_fence *in_fence = NULL;
8 struct sync_file *out_fence = NULL;
9 int out_fence_fd = -1;
int err;
BUILD_BUG_ON(__EXEC_INTERNAL_FLAGS & ~__I915_EXEC_ILLEGAL_FLAGS);
BUILD_BUG_ON(__EXEC_OBJECT_INTERNAL_FLAGS &
~__EXEC_OBJECT_UNKNOWN_FLAGS);
16 eb.i915 = to_i915(dev);
17 eb.file = file;
18 eb.args = args;
19 if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC))
20 args->flags |= __EXEC_HAS_RELOC;
22 eb.exec = exec;
23 eb.vma = (struct i915_vma **)(exec + args->buffer_count + 1);
24 eb.vma[0] = NULL;
25 eb.flags = (unsigned int *)(eb.vma + args->buffer_count + 1);
27 eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
28 if (USES_FULL_PPGTT(eb.i915))
29 eb.invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
30 reloc_cache_init(&eb.reloc_cache, eb.i915);
32 eb.buffer_count = args->buffer_count;
33 eb.batch_start_offset = args->batch_start_offset;
34 eb.batch_len = args->batch_len;
36 eb.batch_flags = 0;
37 if (args->flags & I915_EXEC_SECURE) {
38 if (!drm_is_current_master(file) || !capable(CAP_SYS_ADMIN))
39 return -EPERM;
41 eb.batch_flags |= I915_DISPATCH_SECURE;
}
43 if (args->flags & I915_EXEC_IS_PINNED)
44 eb.batch_flags |= I915_DISPATCH_PINNED;
46 eb.engine = eb_select_engine(eb.i915, file, args);
if (!eb.engine)
48 return -EINVAL;
50 if (args->flags & I915_EXEC_RESOURCE_STREAMER) {
51 if (!HAS_RESOURCE_STREAMER(eb.i915)) {
52 DRM_DEBUG("RS is only allowed for Haswell, Gen8 and above\n");
53 return -EINVAL;
}
55 if (eb.engine->id != RCS) {
56 DRM_DEBUG("RS is not available on %s\n",
eb.engine->name);
58 return -EINVAL;
}
61 eb.batch_flags |= I915_DISPATCH_RS;
}
64 if (args->flags & I915_EXEC_FENCE_IN) {
65 in_fence = sync_file_get_fence(lower_32_bits(args->rsvd2));
66 if (!in_fence)
67 return -EINVAL;
}
70 if (args->flags & I915_EXEC_FENCE_OUT) {
71 out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
72 if (out_fence_fd < 0) {
err = out_fence_fd;
goto err_in_fence;
}
}
78 err = eb_create(&eb);
if (err)
goto err_out_fence;
GEM_BUG_ON(!eb.lut_size);
84 err = eb_select_context(&eb);
if (unlikely(err))
goto err_destroy;
/*
* Take a local wakeref for preparing to dispatch the execbuf as
* we expect to access the hardware fairly frequently in the
* process. Upon first dispatch, we acquire another prolonged
* wakeref that we hold until the GPU has been idle for at least
* 100ms.
*/
95 intel_runtime_pm_get(eb.i915);
97 err = i915_mutex_lock_interruptible(dev);
98 if (err)
goto err_rpm;
101 err = eb_relocate(&eb);
102 if (err) {
/*
* If the user expects the execobject.offset and
* reloc.presumed_offset to be an exact match,
* as for using NO_RELOC, then we cannot update
* the execobject.offset until we have completed
* relocation.
*/
110 args->flags &= ~__EXEC_HAS_RELOC;
111 goto err_vma;
}
114 if (unlikely(*eb.batch->exec_flags & EXEC_OBJECT_WRITE)) {
115 DRM_DEBUG("Attempting to use self-modifying batch buffer\n");
116 err = -EINVAL;
117 goto err_vma;
}
119 if (eb.batch_start_offset > eb.batch->size ||
120 eb.batch_len > eb.batch->size - eb.batch_start_offset) {
121 DRM_DEBUG("Attempting to use out-of-bounds batch\n");
122 err = -EINVAL;
123 goto err_vma;
}
126 if (eb_use_cmdparser(&eb)) {
struct i915_vma *vma;
129 vma = eb_parse(&eb, drm_is_current_master(file));
130 if (IS_ERR(vma)) {
err = PTR_ERR(vma);
goto err_vma;
}
135 if (vma) {
/*
* Batch parsed and accepted:
*
* Set the DISPATCH_SECURE bit to remove the NON_SECURE
* bit from MI_BATCH_BUFFER_START commands issued in
* the dispatch_execbuffer implementations. We
* specifically don't want that set on batches the
* command parser has accepted.
*/
145 eb.batch_flags |= I915_DISPATCH_SECURE;
146 eb.batch_start_offset = 0;
147 eb.batch = vma;
}
}
151 if (eb.batch_len == 0)
152 eb.batch_len = eb.batch->size - eb.batch_start_offset;
/*
* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
* batch" bit. Hence we need to pin secure batches into the global gtt.
* hsw should have this fixed, but bdw mucks it up again. */
158 if (eb.batch_flags & I915_DISPATCH_SECURE) {
struct i915_vma *vma;
/*
* So on first glance it looks freaky that we pin the batch here
* outside of the reservation loop. But:
* - The batch is already pinned into the relevant ppgtt, so we
* already have the backing storage fully allocated.
* - No other BO uses the global gtt (well contexts, but meh),
* so we don't really have issues with multiple objects not
* fitting due to fragmentation.
* So this is actually safe.
*/
171 vma = i915_gem_object_ggtt_pin(eb.batch->obj, NULL, 0, 0, 0);
172 if (IS_ERR(vma)) {
173 err = PTR_ERR(vma);
174 goto err_vma;
}
177 eb.batch = vma;
}
/* All GPU relocation batches must be submitted prior to the user rq */
GEM_BUG_ON(eb.reloc_cache.rq);
/* Allocate a request for this batch buffer nice and early. */
184 eb.request = i915_request_alloc(eb.engine, eb.ctx);
185 if (IS_ERR(eb.request)) {
186 err = PTR_ERR(eb.request);
187 goto err_batch_unpin;
}
190 if (in_fence) {
191 err = i915_request_await_dma_fence(eb.request, in_fence);
192 if (err < 0)
goto err_request;
}
196 if (fences) {
197 err = await_fence_array(&eb, fences);
if (err)
goto err_request;
}
202 if (out_fence_fd != -1) {
203 out_fence = sync_file_create(&eb.request->fence);
204 if (!out_fence) {
err = -ENOMEM;
goto err_request;
}
}
/*
* Whilst this request exists, batch_obj will be on the
* active_list, and so will hold the active reference. Only when this
* request is retired will the the batch_obj be moved onto the
* inactive_list and lose its active reference. Hence we do not need
* to explicitly hold another reference here.
*/
217 eb.request->batch = eb.batch;
219 trace_i915_request_queue(eb.request, eb.batch_flags);
220 err = eb_submit(&eb);
err_request:
222 __i915_request_add(eb.request, err == 0);
223 add_to_client(eb.request, file);
225 if (fences)
226 signal_fence_array(&eb, fences);
228 if (out_fence) {
229 if (err == 0) {
230 fd_install(out_fence_fd, out_fence->file);
args->rsvd2 &= GENMASK_ULL(31, 0); /* keep in-fence */
232 args->rsvd2 |= (u64)out_fence_fd << 32;
233 out_fence_fd = -1;
} else {
235 fput(out_fence->file);
}
}
239 err_batch_unpin:
240 if (eb.batch_flags & I915_DISPATCH_SECURE)
241 i915_vma_unpin(eb.batch);
err_vma:
243 if (eb.exec)
244 eb_release_vmas(&eb);
245 mutex_unlock(&dev->struct_mutex);
err_rpm:
247 intel_runtime_pm_put(eb.i915);
248 i915_gem_context_put(eb.ctx);
err_destroy:
250 eb_destroy(&eb);
err_out_fence:
252 if (out_fence_fd != -1)
253 put_unused_fd(out_fence_fd);
err_in_fence:
255 dma_fence_put(in_fence);
return err;
257 }
static size_t eb_element_size(void)
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment