History

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.

Chris Wilson committed 6 years ago

Commit 88be76c1 parent d13a3176 files · +202 −8Browse files

Unified · Split

6 files
  1. drivers/gpu/drm/i915/Makefile +1 −0
  2. drivers/gpu/drm/i915/gem/i915_gem_context.c +102 −8
  3. drivers/gpu/drm/i915/gt/intel_context_param.c +63 −0
  4. drivers/gpu/drm/i915/gt/intel_context_param.h +14 −0
  5. drivers/gpu/drm/i915/gt/intel_lrc.c +1 −0
  6. include/uapi/drm/i915_drm.h +21 −0
drivers/gpu/drm/i915/Makefile+1−0
@@ -82,6 +82,7 @@ gt-y += \ · 81 unmodified lines
82 gt/gen8_ppgtt.o \82 gt/gen8_ppgtt.o \
83 gt/intel_breadcrumbs.o \83 gt/intel_breadcrumbs.o \
84 gt/intel_context.o \84 gt/intel_context.o \
85 gt/intel_context_param.o \
85 gt/intel_context_sseu.o \86 gt/intel_context_sseu.o \
86 gt/intel_engine_cs.o \87 gt/intel_engine_cs.o \
87 gt/intel_engine_heartbeat.o \88 gt/intel_engine_heartbeat.o \
drivers/gpu/drm/i915/gem/i915_gem_context.c+102−8
@@ -71,6 +71,7 @@ · 70 unmodified lines
71 71
72#include "gt/gen6_ppgtt.h"72#include "gt/gen6_ppgtt.h"
73#include "gt/intel_context.h"73#include "gt/intel_context.h"
74#include "gt/intel_context_param.h"
74#include "gt/intel_engine_heartbeat.h"75#include "gt/intel_engine_heartbeat.h"
75#include "gt/intel_engine_user.h"76#include "gt/intel_engine_user.h"
76#include "gt/intel_ring.h"77#include "gt/intel_ring.h"
@@ -668,23 +669,30 @@ err_free: · 591 unmodified lines
668 return ERR_PTR(err);669 return ERR_PTR(err);
669}670}
670 671
671static void672static int
672context_apply_all(struct i915_gem_context *ctx,673context_apply_all(struct i915_gem_context *ctx,
673 void (*fn)(struct intel_context *ce, void *data),674 int (*fn)(struct intel_context *ce, void *data),
674 void *data)675 void *data)
675{676{
676 struct i915_gem_engines_iter it;677 struct i915_gem_engines_iter it;
677 struct intel_context *ce;678 struct intel_context *ce;
679 int err = 0;
678 680
679 for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it)681 for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
680 fn(ce, data);682 err = fn(ce, data);
683 if (err)
684 break;
685 }
681 i915_gem_context_unlock_engines(ctx);686 i915_gem_context_unlock_engines(ctx);
687
688 return err;
682}689}
683 690
684static void __apply_ppgtt(struct intel_context *ce, void *vm)691static int __apply_ppgtt(struct intel_context *ce, void *vm)
685{692{
686 i915_vm_put(ce->vm);693 i915_vm_put(ce->vm);
687 ce->vm = i915_vm_get(vm);694 ce->vm = i915_vm_get(vm);
695 return 0;
688}696}
689 697
690static struct i915_address_space *698static struct i915_address_space *
@@ -722,9 +730,10 @@ static void __set_timeline(struct intel_timeline **dst, · 31 unmodified lines
722 intel_timeline_put(old);730 intel_timeline_put(old);
723}731}
724 732
725static void __apply_timeline(struct intel_context *ce, void *timeline)733static int __apply_timeline(struct intel_context *ce, void *timeline)
726{734{
727 __set_timeline(&ce->timeline, timeline);735 __set_timeline(&ce->timeline, timeline);
736 return 0;
728}737}
729 738
730static void __assign_timeline(struct i915_gem_context *ctx,739static void __assign_timeline(struct i915_gem_context *ctx,
@@ -1215,6 +1224,63 @@ out: · 484 unmodified lines
1215 return err;1224 return err;
1216}1225}
1217 1226
1227static int __apply_ringsize(struct intel_context *ce, void *sz)
1228{
1229 return intel_context_set_ring_size(ce, (unsigned long)sz);
1230}
1231
1232static int set_ringsize(struct i915_gem_context *ctx,
1233 struct drm_i915_gem_context_param *args)
1234{
1235 if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
1236 return -ENODEV;
1237
1238 if (args->size)
1239 return -EINVAL;
1240
1241 if (!IS_ALIGNED(args->value, I915_GTT_PAGE_SIZE))
1242 return -EINVAL;
1243
1244 if (args->value < I915_GTT_PAGE_SIZE)
1245 return -EINVAL;
1246
1247 if (args->value > 128 * I915_GTT_PAGE_SIZE)
1248 return -EINVAL;
1249
1250 return context_apply_all(ctx,
1251 __apply_ringsize,
1252 __intel_context_ring_size(args->value));
1253}
1254
1255static int __get_ringsize(struct intel_context *ce, void *arg)
1256{
1257 long sz;
1258
1259 sz = intel_context_get_ring_size(ce);
1260 GEM_BUG_ON(sz > INT_MAX);
1261
1262 return sz; /* stop on first engine */
1263}
1264
1265static int get_ringsize(struct i915_gem_context *ctx,
1266 struct drm_i915_gem_context_param *args)
1267{
1268 int sz;
1269
1270 if (!HAS_LOGICAL_RING_CONTEXTS(ctx->i915))
1271 return -ENODEV;
1272
1273 if (args->size)
1274 return -EINVAL;
1275
1276 sz = context_apply_all(ctx, __get_ringsize, NULL);
1277 if (sz < 0)
1278 return sz;
1279
1280 args->value = sz;
1281 return 0;
1282}
1283
1218static int1284static int
1219user_to_context_sseu(struct drm_i915_private *i915,1285user_to_context_sseu(struct drm_i915_private *i915,
1220 const struct drm_i915_gem_context_param_sseu *user,1286 const struct drm_i915_gem_context_param_sseu *user,
@@ -1852,17 +1918,19 @@ set_persistence(struct i915_gem_context *ctx, · 631 unmodified lines
1852 return __context_set_persistence(ctx, args->value);1918 return __context_set_persistence(ctx, args->value);
1853}1919}
1854 1920
1855static void __apply_priority(struct intel_context *ce, void *arg)1921static int __apply_priority(struct intel_context *ce, void *arg)
1856{1922{
1857 struct i915_gem_context *ctx = arg;1923 struct i915_gem_context *ctx = arg;
1858 1924
1859 if (!intel_engine_has_semaphores(ce->engine))1925 if (!intel_engine_has_semaphores(ce->engine))
1860 return;1926 return 0;
1861 1927
1862 if (ctx->sched.priority >= I915_PRIORITY_NORMAL)1928 if (ctx->sched.priority >= I915_PRIORITY_NORMAL)
1863 intel_context_set_use_semaphores(ce);1929 intel_context_set_use_semaphores(ce);
1864 else1930 else
1865 intel_context_clear_use_semaphores(ce);1931 intel_context_clear_use_semaphores(ce);
1932
1933 return 0;
1866}1934}
1867 1935
1868static int set_priority(struct i915_gem_context *ctx,1936static int set_priority(struct i915_gem_context *ctx,
@@ -1955,6 +2023,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv, · 86 unmodified lines
1955 ret = set_persistence(ctx, args);2023 ret = set_persistence(ctx, args);
1956 break;2024 break;
1957 2025
2026 case I915_CONTEXT_PARAM_RINGSIZE:
2027 ret = set_ringsize(ctx, args);
2028 break;
2029
1958 case I915_CONTEXT_PARAM_BAN_PERIOD:2030 case I915_CONTEXT_PARAM_BAN_PERIOD:
1959 default:2031 default:
1960 ret = -EINVAL;2032 ret = -EINVAL;
@@ -1983,6 +2055,18 @@ static int create_setparam(struct i915_user_extension __user *ext, void *data) · 22 unmodified lines
1983 return ctx_setparam(arg->fpriv, arg->ctx, &local.param);2055 return ctx_setparam(arg->fpriv, arg->ctx, &local.param);
1984}2056}
1985 2057
2058static int copy_ring_size(struct intel_context *dst,
2059 struct intel_context *src)
2060{
2061 long sz;
2062
2063 sz = intel_context_get_ring_size(src);
2064 if (sz < 0)
2065 return sz;
2066
2067 return intel_context_set_ring_size(dst, sz);
2068}
2069
1986static int clone_engines(struct i915_gem_context *dst,2070static int clone_engines(struct i915_gem_context *dst,
1987 struct i915_gem_context *src)2071 struct i915_gem_context *src)
1988{2072{
@@ -2026,6 +2110,12 @@ static int clone_engines(struct i915_gem_context *dst, · 37 unmodified lines
2026 }2110 }
2027 2111
2028 intel_context_set_gem(clone->engines[n], dst);2112 intel_context_set_gem(clone->engines[n], dst);
2113
2114 /* Copy across the preferred ringsize */
2115 if (copy_ring_size(clone->engines[n], e->engines[n])) {
2116 __free_engines(clone, n + 1);
2117 goto err_unlock;
2118 }
2029 }2119 }
2030 clone->num_engines = n;2120 clone->num_engines = n;
2031 2121
@@ -2388,6 +2478,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, · 356 unmodified lines
2388 args->value = i915_gem_context_is_persistent(ctx);2478 args->value = i915_gem_context_is_persistent(ctx);
2389 break;2479 break;
2390 2480
2481 case I915_CONTEXT_PARAM_RINGSIZE:
2482 ret = get_ringsize(ctx, args);
2483 break;
2484
2391 case I915_CONTEXT_PARAM_BAN_PERIOD:2485 case I915_CONTEXT_PARAM_BAN_PERIOD:
2392 default:2486 default:
2393 ret = -EINVAL;2487 ret = -EINVAL;
drivers/gpu/drm/i915/gt/intel_context_param.c+63−0
@@ -0,0 +1,63 @@
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2019 Intel Corporation
4 */
5
6#include "i915_active.h"
7#include "intel_context.h"
8#include "intel_context_param.h"
9#include "intel_ring.h"
10
11int intel_context_set_ring_size(struct intel_context *ce, long sz)
12{
13 int err;
14
15 if (intel_context_lock_pinned(ce))
16 return -EINTR;
17
18 err = i915_active_wait(&ce->active);
19 if (err < 0)
20 goto unlock;
21
22 if (intel_context_is_pinned(ce)) {
23 err = -EBUSY; /* In active use, come back later! */
24 goto unlock;
25 }
26
27 if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
28 struct intel_ring *ring;
29
30 /* Replace the existing ringbuffer */
31 ring = intel_engine_create_ring(ce->engine, sz);
32 if (IS_ERR(ring)) {
33 err = PTR_ERR(ring);
34 goto unlock;
35 }
36
37 intel_ring_put(ce->ring);
38 ce->ring = ring;
39
40 /* Context image will be updated on next pin */
41 } else {
42 ce->ring = __intel_context_ring_size(sz);
43 }
44
45unlock:
46 intel_context_unlock_pinned(ce);
47 return err;
48}
49
50long intel_context_get_ring_size(struct intel_context *ce)
51{
52 long sz = (unsigned long)READ_ONCE(ce->ring);
53
54 if (test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) {
55 if (intel_context_lock_pinned(ce))
56 return -EINTR;
57
58 sz = ce->ring->size;
59 intel_context_unlock_pinned(ce);
60 }
61
62 return sz;
63}
drivers/gpu/drm/i915/gt/intel_context_param.h+14−0
@@ -0,0 +1,14 @@
1/* SPDX-License-Identifier: MIT */
2/*
3 * Copyright © 2019 Intel Corporation
4 */
5
6#ifndef INTEL_CONTEXT_PARAM_H
7#define INTEL_CONTEXT_PARAM_H
8
9struct intel_context;
10
11int intel_context_set_ring_size(struct intel_context *ce, long sz);
12long intel_context_get_ring_size(struct intel_context *ce);
13
14#endif /* INTEL_CONTEXT_PARAM_H */
drivers/gpu/drm/i915/gt/intel_lrc.c+1−0
@@ -2966,6 +2966,7 @@ __execlists_update_reg_state(const struct intel_context *ce, · 2965 unmodified lines
2966 regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);2966 regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
2967 regs[CTX_RING_HEAD] = head;2967 regs[CTX_RING_HEAD] = head;
2968 regs[CTX_RING_TAIL] = ring->tail;2968 regs[CTX_RING_TAIL] = ring->tail;
2969 regs[CTX_RING_CTL] = RING_CTL_SIZE(ring->size) | RING_VALID;
2969 2970
2970 /* RPCS */2971 /* RPCS */
2971 if (engine->class == RENDER_CLASS) {2972 if (engine->class == RENDER_CLASS) {
include/uapi/drm/i915_drm.h+21−0
@@ -1619,6 +1619,27 @@ struct drm_i915_gem_context_param { · 1618 unmodified lines
1619 * By default, new contexts allow persistence.1619 * By default, new contexts allow persistence.
1620 */1620 */
1621#define I915_CONTEXT_PARAM_PERSISTENCE 0xb1621#define I915_CONTEXT_PARAM_PERSISTENCE 0xb
1622
1623/*
1624 * I915_CONTEXT_PARAM_RINGSIZE:
1625 *
1626 * Sets the size of the CS ringbuffer to use for logical ring contexts. This
1627 * applies a limit of how many batches can be queued to HW before the caller
1628 * is blocked due to lack of space for more commands.
1629 *
1630 * Only reliably possible to be set prior to first use, i.e. during
1631 * construction. At any later point, the current execution must be flushed as
1632 * the ring can only be changed while the context is idle. Note, the ringsize
1633 * can be specified as a constructor property, see
1634 * I915_CONTEXT_CREATE_EXT_SETPARAM, but can also be set later if required.
1635 *
1636 * Only applies to the current set of engine and lost when those engines
1637 * are replaced by a new mapping (see I915_CONTEXT_PARAM_ENGINES).
1638 *
1639 * Must be between 4 - 512 KiB, in intervals of page size [4 KiB].
1640 * Default is 16 KiB.
1641 */
1642#define I915_CONTEXT_PARAM_RINGSIZE 0xc
1622/* Must be kept compact -- no holes and well documented */1643/* Must be kept compact -- no holes and well documented */
1623 1644
1624 __u64 value;1645 __u64 value;