cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i915_gem_throttle.c (2586B)


      1/*
      2 * SPDX-License-Identifier: MIT
      3 *
      4 * Copyright © 2014-2016 Intel Corporation
      5 */
      6
      7#include <linux/jiffies.h>
      8
      9#include <drm/drm_file.h>
     10
     11#include "i915_drv.h"
     12#include "i915_file_private.h"
     13#include "i915_gem_context.h"
     14#include "i915_gem_ioctls.h"
     15#include "i915_gem_object.h"
     16
     17/*
     18 * 20ms is a fairly arbitrary limit (greater than the average frame time)
     19 * chosen to prevent the CPU getting more than a frame ahead of the GPU
     20 * (when using lax throttling for the frontbuffer). We also use it to
     21 * offer free GPU waitboosts for severely congested workloads.
     22 */
     23#define DRM_I915_THROTTLE_JIFFIES msecs_to_jiffies(20)
     24
     25/*
     26 * Throttle our rendering by waiting until the ring has completed our requests
     27 * emitted over 20 msec ago.
     28 *
     29 * Note that if we were to use the current jiffies each time around the loop,
     30 * we wouldn't escape the function with any frames outstanding if the time to
     31 * render a frame was over 20ms.
     32 *
     33 * This should get us reasonable parallelism between CPU and GPU but also
     34 * relatively low latency when blocking on a particular request to finish.
     35 */
     36int
     37i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
     38			struct drm_file *file)
     39{
     40	const unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES;
     41	struct drm_i915_file_private *file_priv = file->driver_priv;
     42	struct drm_i915_private *i915 = to_i915(dev);
     43	struct i915_gem_context *ctx;
     44	unsigned long idx;
     45	long ret;
     46
     47	/* ABI: return -EIO if already wedged */
     48	ret = intel_gt_terminally_wedged(to_gt(i915));
     49	if (ret)
     50		return ret;
     51
     52	rcu_read_lock();
     53	xa_for_each(&file_priv->context_xa, idx, ctx) {
     54		struct i915_gem_engines_iter it;
     55		struct intel_context *ce;
     56
     57		if (!kref_get_unless_zero(&ctx->ref))
     58			continue;
     59		rcu_read_unlock();
     60
     61		for_each_gem_engine(ce,
     62				    i915_gem_context_lock_engines(ctx),
     63				    it) {
     64			struct i915_request *rq, *target = NULL;
     65
     66			if (!ce->timeline)
     67				continue;
     68
     69			mutex_lock(&ce->timeline->mutex);
     70			list_for_each_entry_reverse(rq,
     71						    &ce->timeline->requests,
     72						    link) {
     73				if (i915_request_completed(rq))
     74					break;
     75
     76				if (time_after(rq->emitted_jiffies,
     77					       recent_enough))
     78					continue;
     79
     80				target = i915_request_get(rq);
     81				break;
     82			}
     83			mutex_unlock(&ce->timeline->mutex);
     84			if (!target)
     85				continue;
     86
     87			ret = i915_request_wait(target,
     88						I915_WAIT_INTERRUPTIBLE,
     89						MAX_SCHEDULE_TIMEOUT);
     90			i915_request_put(target);
     91			if (ret < 0)
     92				break;
     93		}
     94		i915_gem_context_unlock_engines(ctx);
     95		i915_gem_context_put(ctx);
     96
     97		rcu_read_lock();
     98	}
     99	rcu_read_unlock();
    100
    101	return ret < 0 ? ret : 0;
    102}