2022-03-17 05:02:44

by Bob Beckett

[permalink] [raw]
Subject: [RFC PATCH 3/7] drm/i915: use gem objects to track stolen nodes

Construct gem objects around stolen nodes.
This stops the abuse of interfaces and aids future patches that done use
drm nodes for stolen areas.

Signed-off-by: Robert Beckett <[email protected]>
---
drivers/gpu/drm/i915/display/intel_fbc.c | 72 ++++++++++++----------
drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 60 ++++++++++++++++++
drivers/gpu/drm/i915/gem/i915_gem_stolen.h | 7 +++
3 files changed, 106 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index 142280b6ce6d..9df64ecab70e 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -92,8 +92,8 @@ struct intel_fbc {
unsigned int possible_framebuffer_bits;
unsigned int busy_bits;

- struct drm_mm_node compressed_fb;
- struct drm_mm_node compressed_llb;
+ struct drm_i915_gem_object *compressed_fb;
+ struct drm_i915_gem_object *compressed_llb;

enum intel_fbc_id id;

@@ -331,16 +331,18 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc)
static void i8xx_fbc_program_cfb(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;
+ u64 fb_offset = i915_gem_object_stolen_offset(fbc->compressed_fb);
+ u64 llb_offset = i915_gem_object_stolen_offset(fbc->compressed_llb);

GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start,
- fbc->compressed_fb.start, U32_MAX));
+ fb_offset, U32_MAX));
GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start,
- fbc->compressed_llb.start, U32_MAX));
+ llb_offset, U32_MAX));

intel_de_write(i915, FBC_CFB_BASE,
- i915->dsm.start + fbc->compressed_fb.start);
+ i915->dsm.start + fb_offset);
intel_de_write(i915, FBC_LL_BASE,
- i915->dsm.start + fbc->compressed_llb.start);
+ i915->dsm.start + llb_offset);
}

static const struct intel_fbc_funcs i8xx_fbc_funcs = {
@@ -449,7 +451,8 @@ static void g4x_fbc_program_cfb(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;

- intel_de_write(i915, DPFC_CB_BASE, fbc->compressed_fb.start);
+ intel_de_write(i915, DPFC_CB_BASE,
+ i915_gem_object_stolen_offset(fbc->compressed_fb));
}

static const struct intel_fbc_funcs g4x_fbc_funcs = {
@@ -500,7 +503,8 @@ static void ilk_fbc_program_cfb(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;

- intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id), fbc->compressed_fb.start);
+ intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id),
+ i915_gem_object_stolen_offset(fbc->compressed_fb));
}

static const struct intel_fbc_funcs ilk_fbc_funcs = {
@@ -740,21 +744,24 @@ static int find_compression_limit(struct intel_fbc *fbc,
{
struct drm_i915_private *i915 = fbc->i915;
u64 end = intel_fbc_stolen_end(i915);
- int ret, limit = min_limit;
+ int limit = min_limit;
+ struct drm_i915_gem_object *obj;

size /= limit;

/* Try to over-allocate to reduce reallocations and fragmentation. */
- ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb,
- size <<= 1, 4096, 0, end);
- if (ret == 0)
+ obj = i915_gem_object_create_stolen_in_range(i915, size <<= 1, 4096, 0, end);
+ if (!IS_ERR(obj)) {
+ fbc->compressed_fb = obj;
return limit;
+ }

for (; limit <= intel_fbc_max_limit(i915); limit <<= 1) {
- ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb,
- size >>= 1, 4096, 0, end);
- if (ret == 0)
+ obj = i915_gem_object_create_stolen_in_range(i915, size >>= 1, 4096, 0, end);
+ if (!IS_ERR(obj)) {
+ fbc->compressed_fb = obj;
return limit;
+ }
}

return 0;
@@ -765,17 +772,19 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc,
{
struct drm_i915_private *i915 = fbc->i915;
int ret;
+ struct drm_i915_gem_object *obj;

- drm_WARN_ON(&i915->drm,
- drm_mm_node_allocated(&fbc->compressed_fb));
- drm_WARN_ON(&i915->drm,
- drm_mm_node_allocated(&fbc->compressed_llb));
+ drm_WARN_ON(&i915->drm, fbc->compressed_fb);
+ drm_WARN_ON(&i915->drm, fbc->compressed_llb);

if (DISPLAY_VER(i915) < 5 && !IS_G4X(i915)) {
- ret = i915_gem_stolen_insert_node(i915, &fbc->compressed_llb,
- 4096, 4096);
- if (ret)
+ obj = i915_gem_object_create_stolen_in_range(i915, 4096, 4096,
+ I915_GEM_STOLEN_BIAS, U64_MAX);
+ if (IS_ERR(obj)) {
+ ret = PTR_ERR(obj);
goto err;
+ }
+ fbc->compressed_llb = obj;
}

ret = find_compression_limit(fbc, size, min_limit);
@@ -788,14 +797,13 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc,
fbc->limit = ret;

drm_dbg_kms(&i915->drm,
- "reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n",
- fbc->compressed_fb.size, fbc->limit);
+ "reserved %lu bytes of contiguous stolen space for FBC, limit: %d\n",
+ fbc->compressed_fb->base.size, fbc->limit);

return 0;

err_llb:
- if (drm_mm_node_allocated(&fbc->compressed_llb))
- i915_gem_stolen_remove_node(i915, &fbc->compressed_llb);
+ i915_gem_object_put(fetch_and_zero(&fbc->compressed_llb));
err:
if (drm_mm_initialized(&i915->mm.stolen))
drm_info_once(&i915->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
@@ -809,15 +817,13 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc)

static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc)
{
- struct drm_i915_private *i915 = fbc->i915;
-
if (WARN_ON(intel_fbc_hw_is_active(fbc)))
return;

- if (drm_mm_node_allocated(&fbc->compressed_llb))
- i915_gem_stolen_remove_node(i915, &fbc->compressed_llb);
- if (drm_mm_node_allocated(&fbc->compressed_fb))
- i915_gem_stolen_remove_node(i915, &fbc->compressed_fb);
+ if (fbc->compressed_llb)
+ i915_gem_object_put(fetch_and_zero(&fbc->compressed_llb));
+ if (fbc->compressed_fb)
+ i915_gem_object_put(fetch_and_zero(&fbc->compressed_fb));
}

void intel_fbc_cleanup(struct drm_i915_private *i915)
@@ -1023,7 +1029,7 @@ static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state)
struct intel_fbc *fbc = plane->fbc;

return intel_fbc_min_limit(plane_state) <= fbc->limit &&
- intel_fbc_cfb_size(plane_state) <= fbc->compressed_fb.size * fbc->limit;
+ intel_fbc_cfb_size(plane_state) <= fbc->compressed_fb->base.size * fbc->limit;
}

static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index 0bf8f61134af..265133cb2a47 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -907,6 +907,66 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915,
return ERR_PTR(ret);
}

+struct drm_i915_gem_object *
+i915_gem_object_create_stolen_in_range(struct drm_i915_private *i915,
+ resource_size_t size,
+ resource_size_t alignment,
+ u64 start, u64 end)
+{
+ struct intel_memory_region *mem = i915->mm.stolen_region;
+ struct drm_i915_gem_object *obj;
+ struct drm_mm_node *stolen;
+ int ret;
+
+ if (!drm_mm_initialized(&i915->mm.stolen))
+ return ERR_PTR(-ENODEV);
+
+ /* KISS and expect everything to be page-aligned */
+ if (GEM_WARN_ON(size == 0) ||
+ GEM_WARN_ON(!IS_ALIGNED(size, mem->min_page_size)) ||
+ GEM_WARN_ON(!IS_ALIGNED(alignment, mem->min_page_size)))
+ return ERR_PTR(-EINVAL);
+
+ stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
+ if (!stolen)
+ return ERR_PTR(-ENOMEM);
+
+ ret = i915_gem_stolen_insert_node_in_range(i915, stolen, size,
+ alignment, start, end);
+ if (ret)
+ goto err_free;
+
+ obj = i915_gem_object_alloc();
+ if (!obj) {
+ ret = -ENOMEM;
+ goto err_stolen;
+ }
+
+ ret = __i915_gem_object_create_stolen(mem, obj, stolen);
+ if (ret)
+ goto err_object_free;
+
+ i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
+ return obj;
+
+err_object_free:
+ i915_gem_object_free(obj);
+err_stolen:
+ i915_gem_stolen_remove_node(i915, stolen);
+err_free:
+ kfree(stolen);
+ return ERR_PTR(ret);
+}
+
+u64 i915_gem_object_stolen_offset(const struct drm_i915_gem_object *obj)
+{
+ if (!obj || !i915_gem_object_is_stolen(obj))
+ return 0;
+
+ return obj->stolen->start;
+}
+
+
bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj)
{
return obj->ops == &i915_gem_object_stolen_ops;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
index ccdf7befc571..494e90f130f4 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
@@ -35,6 +35,13 @@ struct drm_i915_gem_object *
i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv,
resource_size_t stolen_offset,
resource_size_t size);
+struct drm_i915_gem_object *
+i915_gem_object_create_stolen_in_range(struct drm_i915_private *i915,
+ resource_size_t size,
+ resource_size_t alignment,
+ u64 start, u64 end);
+u64 i915_gem_object_stolen_offset(const struct drm_i915_gem_object *obj);
+

bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj);

--
2.25.1