1c349dbc7Sjsg /*
2c349dbc7Sjsg * SPDX-License-Identifier: MIT
3c349dbc7Sjsg *
4c349dbc7Sjsg * Copyright © 2016 Intel Corporation
5c349dbc7Sjsg */
6c349dbc7Sjsg
7c349dbc7Sjsg #include <linux/dma-fence-array.h>
85ca02815Sjsg #include <linux/dma-fence-chain.h>
9c349dbc7Sjsg #include <linux/jiffies.h>
10c349dbc7Sjsg
11c349dbc7Sjsg #include "gt/intel_engine.h"
121bb76ff1Sjsg #include "gt/intel_rps.h"
13c349dbc7Sjsg
14c349dbc7Sjsg #include "i915_gem_ioctls.h"
15c349dbc7Sjsg #include "i915_gem_object.h"
16c349dbc7Sjsg
17c349dbc7Sjsg static long
i915_gem_object_wait_fence(struct dma_fence * fence,unsigned int flags,long timeout)18c349dbc7Sjsg i915_gem_object_wait_fence(struct dma_fence *fence,
19c349dbc7Sjsg unsigned int flags,
20c349dbc7Sjsg long timeout)
21c349dbc7Sjsg {
22c349dbc7Sjsg BUILD_BUG_ON(I915_WAIT_INTERRUPTIBLE != 0x1);
23c349dbc7Sjsg
24c349dbc7Sjsg if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
25c349dbc7Sjsg return timeout;
26c349dbc7Sjsg
27c349dbc7Sjsg if (dma_fence_is_i915(fence))
281bb76ff1Sjsg return i915_request_wait_timeout(to_request(fence), flags, timeout);
29c349dbc7Sjsg
30c349dbc7Sjsg return dma_fence_wait_timeout(fence,
31c349dbc7Sjsg flags & I915_WAIT_INTERRUPTIBLE,
32c349dbc7Sjsg timeout);
33c349dbc7Sjsg }
34c349dbc7Sjsg
351bb76ff1Sjsg static void
i915_gem_object_boost(struct dma_resv * resv,unsigned int flags)361bb76ff1Sjsg i915_gem_object_boost(struct dma_resv *resv, unsigned int flags)
371bb76ff1Sjsg {
381bb76ff1Sjsg struct dma_resv_iter cursor;
391bb76ff1Sjsg struct dma_fence *fence;
401bb76ff1Sjsg
411bb76ff1Sjsg /*
421bb76ff1Sjsg * Prescan all fences for potential boosting before we begin waiting.
431bb76ff1Sjsg *
441bb76ff1Sjsg * When we wait, we wait on outstanding fences serially. If the
451bb76ff1Sjsg * dma-resv contains a sequence such as 1:1, 1:2 instead of a reduced
461bb76ff1Sjsg * form 1:2, then as we look at each wait in turn we see that each
471bb76ff1Sjsg * request is currently executing and not worthy of boosting. But if
481bb76ff1Sjsg * we only happen to look at the final fence in the sequence (because
491bb76ff1Sjsg * of request coalescing or splitting between read/write arrays by
501bb76ff1Sjsg * the iterator), then we would boost. As such our decision to boost
511bb76ff1Sjsg * or not is delicately balanced on the order we wait on fences.
521bb76ff1Sjsg *
531bb76ff1Sjsg * So instead of looking for boosts sequentially, look for all boosts
541bb76ff1Sjsg * upfront and then wait on the outstanding fences.
551bb76ff1Sjsg */
561bb76ff1Sjsg
571bb76ff1Sjsg dma_resv_iter_begin(&cursor, resv,
581bb76ff1Sjsg dma_resv_usage_rw(flags & I915_WAIT_ALL));
591bb76ff1Sjsg dma_resv_for_each_fence_unlocked(&cursor, fence)
601bb76ff1Sjsg if (dma_fence_is_i915(fence) &&
611bb76ff1Sjsg !i915_request_started(to_request(fence)))
621bb76ff1Sjsg intel_rps_boost(to_request(fence));
631bb76ff1Sjsg dma_resv_iter_end(&cursor);
641bb76ff1Sjsg }
651bb76ff1Sjsg
66c349dbc7Sjsg static long
i915_gem_object_wait_reservation(struct dma_resv * resv,unsigned int flags,long timeout)67c349dbc7Sjsg i915_gem_object_wait_reservation(struct dma_resv *resv,
68c349dbc7Sjsg unsigned int flags,
69c349dbc7Sjsg long timeout)
70c349dbc7Sjsg {
711bb76ff1Sjsg struct dma_resv_iter cursor;
721bb76ff1Sjsg struct dma_fence *fence;
731bb76ff1Sjsg long ret = timeout ?: 1;
74c349dbc7Sjsg
751bb76ff1Sjsg i915_gem_object_boost(resv, flags);
76c349dbc7Sjsg
771bb76ff1Sjsg dma_resv_iter_begin(&cursor, resv,
781bb76ff1Sjsg dma_resv_usage_rw(flags & I915_WAIT_ALL));
791bb76ff1Sjsg dma_resv_for_each_fence_unlocked(&cursor, fence) {
801bb76ff1Sjsg ret = i915_gem_object_wait_fence(fence, flags, timeout);
811bb76ff1Sjsg if (ret <= 0)
82c349dbc7Sjsg break;
83c349dbc7Sjsg
841bb76ff1Sjsg if (timeout)
851bb76ff1Sjsg timeout = ret;
86c349dbc7Sjsg }
871bb76ff1Sjsg dma_resv_iter_end(&cursor);
88c349dbc7Sjsg
891bb76ff1Sjsg return ret;
90c349dbc7Sjsg }
91c349dbc7Sjsg
fence_set_priority(struct dma_fence * fence,const struct i915_sched_attr * attr)925ca02815Sjsg static void fence_set_priority(struct dma_fence *fence,
93c349dbc7Sjsg const struct i915_sched_attr *attr)
94c349dbc7Sjsg {
95c349dbc7Sjsg struct i915_request *rq;
96c349dbc7Sjsg struct intel_engine_cs *engine;
97c349dbc7Sjsg
98c349dbc7Sjsg if (dma_fence_is_signaled(fence) || !dma_fence_is_i915(fence))
99c349dbc7Sjsg return;
100c349dbc7Sjsg
101c349dbc7Sjsg rq = to_request(fence);
102c349dbc7Sjsg engine = rq->engine;
103c349dbc7Sjsg
104c349dbc7Sjsg rcu_read_lock(); /* RCU serialisation for set-wedged protection */
1055ca02815Sjsg if (engine->sched_engine->schedule)
1065ca02815Sjsg engine->sched_engine->schedule(rq, attr);
107c349dbc7Sjsg rcu_read_unlock();
108c349dbc7Sjsg }
109c349dbc7Sjsg
__dma_fence_is_chain(const struct dma_fence * fence)1105ca02815Sjsg static inline bool __dma_fence_is_chain(const struct dma_fence *fence)
1115ca02815Sjsg {
1125ca02815Sjsg return fence->ops == &dma_fence_chain_ops;
1135ca02815Sjsg }
1145ca02815Sjsg
i915_gem_fence_wait_priority(struct dma_fence * fence,const struct i915_sched_attr * attr)1155ca02815Sjsg void i915_gem_fence_wait_priority(struct dma_fence *fence,
116c349dbc7Sjsg const struct i915_sched_attr *attr)
117c349dbc7Sjsg {
1185ca02815Sjsg if (dma_fence_is_signaled(fence))
1195ca02815Sjsg return;
1205ca02815Sjsg
1215ca02815Sjsg local_bh_disable();
1225ca02815Sjsg
123c349dbc7Sjsg /* Recurse once into a fence-array */
124c349dbc7Sjsg if (dma_fence_is_array(fence)) {
125c349dbc7Sjsg struct dma_fence_array *array = to_dma_fence_array(fence);
126c349dbc7Sjsg int i;
127c349dbc7Sjsg
128c349dbc7Sjsg for (i = 0; i < array->num_fences; i++)
1295ca02815Sjsg fence_set_priority(array->fences[i], attr);
1305ca02815Sjsg } else if (__dma_fence_is_chain(fence)) {
1315ca02815Sjsg struct dma_fence *iter;
1325ca02815Sjsg
1335ca02815Sjsg /* The chain is ordered; if we boost the last, we boost all */
1345ca02815Sjsg dma_fence_chain_for_each(iter, fence) {
1355ca02815Sjsg fence_set_priority(to_dma_fence_chain(iter)->fence,
1365ca02815Sjsg attr);
1375ca02815Sjsg break;
138c349dbc7Sjsg }
1395ca02815Sjsg dma_fence_put(iter);
1405ca02815Sjsg } else {
1415ca02815Sjsg fence_set_priority(fence, attr);
1425ca02815Sjsg }
1435ca02815Sjsg
1445ca02815Sjsg local_bh_enable(); /* kick the tasklets if queues were reprioritised */
145c349dbc7Sjsg }
146c349dbc7Sjsg
147c349dbc7Sjsg int
i915_gem_object_wait_priority(struct drm_i915_gem_object * obj,unsigned int flags,const struct i915_sched_attr * attr)148c349dbc7Sjsg i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
149c349dbc7Sjsg unsigned int flags,
150c349dbc7Sjsg const struct i915_sched_attr *attr)
151c349dbc7Sjsg {
1521bb76ff1Sjsg struct dma_resv_iter cursor;
1531bb76ff1Sjsg struct dma_fence *fence;
154c349dbc7Sjsg
1551bb76ff1Sjsg dma_resv_iter_begin(&cursor, obj->base.resv,
1561bb76ff1Sjsg dma_resv_usage_rw(flags & I915_WAIT_ALL));
1571bb76ff1Sjsg dma_resv_for_each_fence_unlocked(&cursor, fence)
1581bb76ff1Sjsg i915_gem_fence_wait_priority(fence, attr);
1591bb76ff1Sjsg dma_resv_iter_end(&cursor);
160c349dbc7Sjsg return 0;
161c349dbc7Sjsg }
162c349dbc7Sjsg
163c349dbc7Sjsg /**
164*f005ef32Sjsg * i915_gem_object_wait - Waits for rendering to the object to be completed
165c349dbc7Sjsg * @obj: i915 gem object
166c349dbc7Sjsg * @flags: how to wait (under a lock, for all rendering or just for writes etc)
167c349dbc7Sjsg * @timeout: how long to wait
168c349dbc7Sjsg */
169c349dbc7Sjsg int
i915_gem_object_wait(struct drm_i915_gem_object * obj,unsigned int flags,long timeout)170c349dbc7Sjsg i915_gem_object_wait(struct drm_i915_gem_object *obj,
171c349dbc7Sjsg unsigned int flags,
172c349dbc7Sjsg long timeout)
173c349dbc7Sjsg {
174c349dbc7Sjsg might_sleep();
175c349dbc7Sjsg GEM_BUG_ON(timeout < 0);
176c349dbc7Sjsg
177c349dbc7Sjsg timeout = i915_gem_object_wait_reservation(obj->base.resv,
178c349dbc7Sjsg flags, timeout);
1791bb76ff1Sjsg
1801bb76ff1Sjsg if (timeout < 0)
1811bb76ff1Sjsg return timeout;
1821bb76ff1Sjsg
1831bb76ff1Sjsg return !timeout ? -ETIME : 0;
184c349dbc7Sjsg }
185c349dbc7Sjsg
nsecs_to_jiffies_timeout(const u64 n)186c349dbc7Sjsg static inline unsigned long nsecs_to_jiffies_timeout(const u64 n)
187c349dbc7Sjsg {
188c349dbc7Sjsg /* nsecs_to_jiffies64() does not guard against overflow */
189*f005ef32Sjsg if ((NSEC_PER_SEC % HZ) != 0 &&
190c349dbc7Sjsg div_u64(n, NSEC_PER_SEC) >= MAX_JIFFY_OFFSET / HZ)
191c349dbc7Sjsg return MAX_JIFFY_OFFSET;
192c349dbc7Sjsg
193c349dbc7Sjsg return min_t(u64, MAX_JIFFY_OFFSET, nsecs_to_jiffies64(n) + 1);
194c349dbc7Sjsg }
195c349dbc7Sjsg
to_wait_timeout(s64 timeout_ns)196c349dbc7Sjsg static unsigned long to_wait_timeout(s64 timeout_ns)
197c349dbc7Sjsg {
198c349dbc7Sjsg if (timeout_ns < 0)
199c349dbc7Sjsg return MAX_SCHEDULE_TIMEOUT;
200c349dbc7Sjsg
201c349dbc7Sjsg if (timeout_ns == 0)
202c349dbc7Sjsg return 0;
203c349dbc7Sjsg
204c349dbc7Sjsg return nsecs_to_jiffies_timeout(timeout_ns);
205c349dbc7Sjsg }
206c349dbc7Sjsg
207c349dbc7Sjsg /**
208c349dbc7Sjsg * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT
209c349dbc7Sjsg * @dev: drm device pointer
210c349dbc7Sjsg * @data: ioctl data blob
211c349dbc7Sjsg * @file: drm file pointer
212c349dbc7Sjsg *
213c349dbc7Sjsg * Returns 0 if successful, else an error is returned with the remaining time in
214c349dbc7Sjsg * the timeout parameter.
215c349dbc7Sjsg * -ETIME: object is still busy after timeout
216c349dbc7Sjsg * -ERESTARTSYS: signal interrupted the wait
217c349dbc7Sjsg * -ENONENT: object doesn't exist
218c349dbc7Sjsg * Also possible, but rare:
219c349dbc7Sjsg * -EAGAIN: incomplete, restart syscall
220c349dbc7Sjsg * -ENOMEM: damn
221c349dbc7Sjsg * -ENODEV: Internal IRQ fail
222c349dbc7Sjsg * -E?: The add request failed
223c349dbc7Sjsg *
224c349dbc7Sjsg * The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any
225c349dbc7Sjsg * non-zero timeout parameter the wait ioctl will wait for the given number of
226c349dbc7Sjsg * nanoseconds on an object becoming unbusy. Since the wait itself does so
227c349dbc7Sjsg * without holding struct_mutex the object may become re-busied before this
228c349dbc7Sjsg * function completes. A similar but shorter * race condition exists in the busy
229c349dbc7Sjsg * ioctl
230c349dbc7Sjsg */
231c349dbc7Sjsg int
i915_gem_wait_ioctl(struct drm_device * dev,void * data,struct drm_file * file)232c349dbc7Sjsg i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
233c349dbc7Sjsg {
234c349dbc7Sjsg struct drm_i915_gem_wait *args = data;
235c349dbc7Sjsg struct drm_i915_gem_object *obj;
236c349dbc7Sjsg ktime_t start;
237c349dbc7Sjsg long ret;
238c349dbc7Sjsg
239c349dbc7Sjsg if (args->flags != 0)
240c349dbc7Sjsg return -EINVAL;
241c349dbc7Sjsg
242c349dbc7Sjsg obj = i915_gem_object_lookup(file, args->bo_handle);
243c349dbc7Sjsg if (!obj)
244c349dbc7Sjsg return -ENOENT;
245c349dbc7Sjsg
246c349dbc7Sjsg start = ktime_get();
247c349dbc7Sjsg
248c349dbc7Sjsg ret = i915_gem_object_wait(obj,
249c349dbc7Sjsg I915_WAIT_INTERRUPTIBLE |
250c349dbc7Sjsg I915_WAIT_PRIORITY |
251c349dbc7Sjsg I915_WAIT_ALL,
252c349dbc7Sjsg to_wait_timeout(args->timeout_ns));
253c349dbc7Sjsg
254c349dbc7Sjsg if (args->timeout_ns > 0) {
255c349dbc7Sjsg args->timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start));
256c349dbc7Sjsg if (args->timeout_ns < 0)
257c349dbc7Sjsg args->timeout_ns = 0;
258c349dbc7Sjsg
259c349dbc7Sjsg /*
260c349dbc7Sjsg * Apparently ktime isn't accurate enough and occasionally has a
261c349dbc7Sjsg * bit of mismatch in the jiffies<->nsecs<->ktime loop. So patch
262c349dbc7Sjsg * things up to make the test happy. We allow up to 1 jiffy.
263c349dbc7Sjsg *
264c349dbc7Sjsg * This is a regression from the timespec->ktime conversion.
265c349dbc7Sjsg */
266c349dbc7Sjsg if (ret == -ETIME && !nsecs_to_jiffies(args->timeout_ns))
267c349dbc7Sjsg args->timeout_ns = 0;
268c349dbc7Sjsg
269c349dbc7Sjsg /* Asked to wait beyond the jiffie/scheduler precision? */
270c349dbc7Sjsg if (ret == -ETIME && args->timeout_ns)
271c349dbc7Sjsg ret = -EAGAIN;
272c349dbc7Sjsg }
273c349dbc7Sjsg
274c349dbc7Sjsg i915_gem_object_put(obj);
275c349dbc7Sjsg return ret;
276c349dbc7Sjsg }
2775ca02815Sjsg
2785ca02815Sjsg /**
2795ca02815Sjsg * i915_gem_object_wait_migration - Sync an accelerated migration operation
2805ca02815Sjsg * @obj: The migrating object.
2815ca02815Sjsg * @flags: waiting flags. Currently supports only I915_WAIT_INTERRUPTIBLE.
2825ca02815Sjsg *
2835ca02815Sjsg * Wait for any pending async migration operation on the object,
2845ca02815Sjsg * whether it's explicitly (i915_gem_object_migrate()) or implicitly
2855ca02815Sjsg * (swapin, initial clearing) initiated.
2865ca02815Sjsg *
2875ca02815Sjsg * Return: 0 if successful, -ERESTARTSYS if a signal was hit during waiting.
2885ca02815Sjsg */
i915_gem_object_wait_migration(struct drm_i915_gem_object * obj,unsigned int flags)2895ca02815Sjsg int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj,
2905ca02815Sjsg unsigned int flags)
2915ca02815Sjsg {
2925ca02815Sjsg might_sleep();
2931bb76ff1Sjsg
2941bb76ff1Sjsg return i915_gem_object_wait_moving_fence(obj, !!(flags & I915_WAIT_INTERRUPTIBLE));
2955ca02815Sjsg }
296