Commit 88be76cd authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915: Allow userspace to specify ringsize on construction

No good reason why we must always use a static ringsize, so let
userspace select one during construction.

Link: https://github.com/intel/compute-runtime/pull/261


Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Steve Carbonari <steven.carbonari@intel.com>
Reviewed-by: default avatarJanusz Krzysztofik <janusz.krzysztofik@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200225192206.1107336-2-chris@chris-wilson.co.uk
parent d13a3177
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -82,6 +82,7 @@ gt-y += \
	gt/gen8_ppgtt.o \
	gt/gen8_ppgtt.o \
	gt/intel_breadcrumbs.o \
	gt/intel_breadcrumbs.o \
	gt/intel_context.o \
	gt/intel_context.o \
	gt/intel_context_param.o \
	gt/intel_context_sseu.o \
	gt/intel_context_sseu.o \
	gt/intel_engine_cs.o \
	gt/intel_engine_cs.o \
	gt/intel_engine_heartbeat.o \
	gt/intel_engine_heartbeat.o \
+102 −8
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@


#include "gt/gen6_ppgtt.h"
#include "gt/gen6_ppgtt.h"
#include "gt/intel_context.h"
#include "gt/intel_context.h"
#include "gt/intel_context_param.h"
#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_ring.h"
#include "gt/intel_ring.h"
@@ -668,23 +669,30 @@ err_free:
	return ERR_PTR(err);
	return ERR_PTR(err);
}
}


static void
static int
context_apply_all(struct i915_gem_context *ctx,
context_apply_all(struct i915_gem_context *ctx,
		  void (*fn)(struct intel_context *ce, void *data),
		  int (*fn)(struct intel_context *ce, void *data),
		  void *data)
		  void *data)
{
{
	struct i915_gem_engines_iter it;
	struct i915_gem_engines_iter it;
	struct intel_context *ce;
	struct intel_context *ce;
	int err = 0;


	for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)
	for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
		fn(ce, data);
		err = fn(ce, data);
		if (err)
			break;
	}
	i915_gem_context_unlock_engines(ctx);
	i915_gem_context_unlock_engines(ctx);

	return err;
}
}


static void __apply_ppgtt(struct intel_context *ce, void *vm)
static int __apply_ppgtt(struct intel_context *ce, void *vm)
{
{
	i915_vm_put(ce->vm);
	i915_vm_put(ce->vm);
	ce->vm = i915_vm_get(vm);
	ce->vm = i915_vm_get(vm);
	return 0;
}
}


static struct i915_address_space *
static struct i915_address_space *
@@ -722,9 +730,10 @@ static void __set_timeline(struct intel_timeline **dst,
		intel_timeline_put(old);
		intel_timeline_put(old);
}
}


static void __apply_timeline(struct intel_context *ce, void *timeline)
static int __apply_timeline(struct intel_context *ce, void *timeline)
{
{
	__set_timeline(&ce->timeline, timeline);
	__set_timeline(&ce->timeline, timeline);
	return 0;
}
}


static void __assign_timeline(struct i915_gem_context *ctx,
static void __assign_timeline(struct i915_gem_context *ctx,
@@ -1215,6 +1224,63 @@ out:
	return err;
	return err;
}
}


static int __apply_ringsize(struct intel_context *ce, void *sz)
{
	return intel_context_set_ring_size(ce, (unsigned long)sz);
}

static int set_ringsize(struct i915_gem_context *ctx,
			struct drm_i915_gem_context_param *args)
{
	if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
		return -ENODEV;

	if (args->size)
		return -EINVAL;

	if (!IS_ALIGNED(args->value, I915_GTT_PAGE_SIZE))
		return -EINVAL;

	if (args->value < I915_GTT_PAGE_SIZE)
		return -EINVAL;

	if (args->value > 128 * I915_GTT_PAGE_SIZE)
		return -EINVAL;

	return context_apply_all(ctx,
				 __apply_ringsize,
				 __intel_context_ring_size(args->value));
}

static int __get_ringsize(struct intel_context *ce, void *arg)
{
	long sz;

	sz = intel_context_get_ring_size(ce);
	GEM_BUG_ON(sz > INT_MAX);

	return sz; /* stop on first engine */
}

static int get_ringsize(struct i915_gem_context *ctx,
			struct drm_i915_gem_context_param *args)
{
	int sz;

	if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
		return -ENODEV;

	if (args->size)
		return -EINVAL;

	sz = context_apply_all(ctx, __get_ringsize, NULL);
	if (sz < 0)
		return sz;

	args->value = sz;
	return 0;
}

static int
static int
user_to_context_sseu(struct drm_i915_private *i915,
user_to_context_sseu(struct drm_i915_private *i915,
		     const struct drm_i915_gem_context_param_sseu *user,
		     const struct drm_i915_gem_context_param_sseu *user,
@@ -1852,17 +1918,19 @@ set_persistence(struct i915_gem_context *ctx,
	return __context_set_persistence(ctx, args->value);
	return __context_set_persistence(ctx, args->value);
}
}


static void __apply_priority(struct intel_context *ce, void *arg)
static int __apply_priority(struct intel_context *ce, void *arg)
{
{
	struct i915_gem_context *ctx = arg;
	struct i915_gem_context *ctx = arg;


	if (!intel_engine_has_semaphores(ce->engine))
	if (!intel_engine_has_semaphores(ce->engine))
		return;
		return 0;


	if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
	if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
		intel_context_set_use_semaphores(ce);
		intel_context_set_use_semaphores(ce);
	else
	else
		intel_context_clear_use_semaphores(ce);
		intel_context_clear_use_semaphores(ce);

	return 0;
}
}


static int set_priority(struct i915_gem_context *ctx,
static int set_priority(struct i915_gem_context *ctx,
@@ -1955,6 +2023,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
		ret = set_persistence(ctx, args);
		ret = set_persistence(ctx, args);
		break;
		break;


	case I915_CONTEXT_PARAM_RINGSIZE:
		ret = set_ringsize(ctx, args);
		break;

	case I915_CONTEXT_PARAM_BAN_PERIOD:
	case I915_CONTEXT_PARAM_BAN_PERIOD:
	default:
	default:
		ret = -EINVAL;
		ret = -EINVAL;
@@ -1983,6 +2055,18 @@ static int create_setparam(struct i915_user_extension __user *ext, void *data)
	return ctx_setparam(arg->fpriv, arg->ctx, &local.param);
	return ctx_setparam(arg->fpriv, arg->ctx, &local.param);
}
}


static int copy_ring_size(struct intel_context *dst,
			  struct intel_context *src)
{
	long sz;

	sz = intel_context_get_ring_size(src);
	if (sz < 0)
		return sz;

	return intel_context_set_ring_size(dst, sz);
}

static int clone_engines(struct i915_gem_context *dst,
static int clone_engines(struct i915_gem_context *dst,
			 struct i915_gem_context *src)
			 struct i915_gem_context *src)
{
{
@@ -2026,6 +2110,12 @@ static int clone_engines(struct i915_gem_context *dst,
		}
		}


		intel_context_set_gem(clone->engines[n], dst);
		intel_context_set_gem(clone->engines[n], dst);

		/* Copy across the preferred ringsize */
		if (copy_ring_size(clone->engines[n], e->engines[n])) {
			__free_engines(clone, n + 1);
			goto err_unlock;
		}
	}
	}
	clone->num_engines = n;
	clone->num_engines = n;


@@ -2388,6 +2478,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
		args->value = i915_gem_context_is_persistent(ctx);
		args->value = i915_gem_context_is_persistent(ctx);
		break;
		break;


	case I915_CONTEXT_PARAM_RINGSIZE:
		ret = get_ringsize(ctx, args);
		break;

	case I915_CONTEXT_PARAM_BAN_PERIOD:
	case I915_CONTEXT_PARAM_BAN_PERIOD:
	default:
	default:
		ret = -EINVAL;
		ret = -EINVAL;
+63 −0
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: MIT
/*
 * Copyright © 2019 Intel Corporation
 */

#include "i915_active.h"
#include "intel_context.h"
#include "intel_context_param.h"
#include "intel_ring.h"

int intel_context_set_ring_size(struct intel_context *ce, long sz)
{
	int err;

	if (intel_context_lock_pinned(ce))
		return -EINTR;

	err = i915_active_wait(&ce->active);
	if (err < 0)
		goto unlock;

	if (intel_context_is_pinned(ce)) {
		err = -EBUSY; /* In active use, come back later! */
		goto unlock;
	}

	if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
		struct intel_ring *ring;

		/* Replace the existing ringbuffer */
		ring = intel_engine_create_ring(ce->engine, sz);
		if (IS_ERR(ring)) {
			err = PTR_ERR(ring);
			goto unlock;
		}

		intel_ring_put(ce->ring);
		ce->ring = ring;

		/* Context image will be updated on next pin */
	} else {
		ce->ring = __intel_context_ring_size(sz);
	}

unlock:
	intel_context_unlock_pinned(ce);
	return err;
}

long intel_context_get_ring_size(struct intel_context *ce)
{
	long sz = (unsigned long)READ_ONCE(ce->ring);

	if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
		if (intel_context_lock_pinned(ce))
			return -EINTR;

		sz = ce->ring->size;
		intel_context_unlock_pinned(ce);
	}

	return sz;
}
+14 −0
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2019 Intel Corporation
 */

#ifndef INTEL_CONTEXT_PARAM_H
#define INTEL_CONTEXT_PARAM_H

struct intel_context;

int intel_context_set_ring_size(struct intel_context *ce, long sz);
long intel_context_get_ring_size(struct intel_context *ce);

#endif /* INTEL_CONTEXT_PARAM_H */
+1 −0
Original line number Original line Diff line number Diff line
@@ -2966,6 +2966,7 @@ __execlists_update_reg_state(const struct intel_context *ce,
	regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
	regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
	regs[CTX_RING_HEAD] = head;
	regs[CTX_RING_HEAD] = head;
	regs[CTX_RING_TAIL] = ring->tail;
	regs[CTX_RING_TAIL] = ring->tail;
	regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID;


	/* RPCS */
	/* RPCS */
	if (engine->class == RENDER_CLASS) {
	if (engine->class == RENDER_CLASS) {
Loading