[RFC 1/2] drm/i915: Offsets for golden context BB modification

Arun Siluvery
2015-07-10T17:35:27Z

From: Armin Reese <armin.c.reese@intel.com>

Golden context batch buffers now contain a set of offsets
at which contents can optionally be modified. This allows
the driver to customize the GC batch for various chipsets
in a GEN family.

v1 - Originally, the i915 driver was only allowed to
insert MI_BATCH_BUFFER_END commands at locations
specified by "alternate_bbend_offsets".

v2 - The previous "alternate_bbend_offsets" field has
been generalized in this version to allow the driver to
modify ranges of DWORDs in the golden context BB. These
ranges are described in "mod_values" structs.

Signed-off-by: Armin Reese <armin.c.reese@intel.com>
Signed-off-by: Arun Siluvery <arun.siluvery@linux.intel.com>
---
drivers/gpu/drm/i915/i915_gem_render_state.c | 65 +++++++++++++++++++++++++--
drivers/gpu/drm/i915/i915_gem_render_state.h | 7 +++
drivers/gpu/drm/i915/intel_renderstate.h | 6 ++-
drivers/gpu/drm/i915/intel_renderstate_gen6.c | 4 ++
drivers/gpu/drm/i915/intel_renderstate_gen7.c | 4 ++
drivers/gpu/drm/i915/intel_renderstate_gen8.c | 4 ++
drivers/gpu/drm/i915/intel_renderstate_gen9.c | 4 ++
7 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c
index a0201fc..818233d 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.c
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.c
@@ -45,6 +45,49 @@ render_state_get_rodata(struct drm_device *dev, const int gen)
return NULL;
}

+/**
+ * Offsets for golden context "value modifications" defined in
+ * intel_renderstate_genx.c are locations in the batch buffer
+ * where the driver is allowed to modify one or more DWORDs
+ * to customize instructions for the GEN platform present.
+ */
+static int gc_modify_values(struct drm_device *dev,
+ const struct intel_renderstate_rodata *rodata,
+ u32 *d)
+{
+ /* Init index to "nothing to modify" value */
+ int mod_index = -1;
+ int mod_val[1];
+ int num_vals = 0;
+
+ /* Write required value(s) to the specified offset(s) */
+ if ((mod_index >= 0) &&
+ (num_vals > 0)) {
+ if (mod_index < rodata->mod_value_items) {
+ int mod_offset, mod_max_cnt, i;
+
+ mod_offset =
+ rodata->mod_values[mod_index].offset;
+ mod_max_cnt =
+ rodata->mod_values[mod_index].max_cnt;
+
+ /* Check for DWORD aligned address, et al */
+ if ((num_vals > mod_max_cnt) ||
+ (mod_offset <= 0) ||
+ (mod_offset > PAGE_SIZE - (mod_max_cnt * sizeof(u32))) ||
+ ((mod_offset & (sizeof(u32) - 1)) != 0))
+ return -EINVAL;
+
+ for (i = 0; i < num_vals; i++) {
+ d[(mod_offset/sizeof(u32)) + i] = mod_val[i];
+ }
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int render_state_init(struct render_state *so, struct drm_device *dev)
{
int ret;
@@ -73,7 +116,7 @@ free_gem:
return ret;
}

-static int render_state_setup(struct render_state *so)
+static int render_state_setup(struct render_state *so, struct drm_device *dev)
{
const struct intel_renderstate_rodata *rodata = so->rodata;
unsigned int i = 0, reloc_index = 0;
@@ -89,10 +132,11 @@ static int render_state_setup(struct render_state *so)
d = kmap(page);

while (i < rodata->batch_items) {
- u32 s = rodata->batch[i];
+ u32 s = rodata->batch[i]; /* DWORD from R/O batch */

if (i * 4 == rodata->reloc[reloc_index]) {
- u64 r = s + so->ggtt_offset;
+ u64 r = s + /* Object offset stored in reloc DWORD */
+ so->ggtt_offset; /* Batch buffer gfx offset */
s = lower_32_bits(r);
if (so->gen >= 8) {
if (i + 1 >= rodata->batch_items ||
@@ -108,8 +152,21 @@ static int render_state_setup(struct render_state *so)

d[i++] = s;
}
+
+ /* Any golden context BB entries to modify? */
+ if ((rodata->mod_values[0].offset != -1) &&
+ (rodata->mod_values[0].max_cnt > 0))
+ ret = gc_modify_values(dev, rodata, d);
+ else
+ ret = 0;
+
kunmap(page);

+ if (ret) {
+ DRM_ERROR("error modifying golden context batch buffer contents\n");
+ return ret;
+ }
+
ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
if (ret)
return ret;
@@ -143,7 +200,7 @@ int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
if (so->rodata == NULL)
return 0;

- ret = render_state_setup(so);
+ ret = render_state_setup(so, ring->dev);
if (ret) {
i915_gem_render_state_fini(so);
return ret;
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.h b/drivers/gpu/drm/i915/i915_gem_render_state.h
index 7aa7372..0898559 100644
--- a/drivers/gpu/drm/i915/i915_gem_render_state.h
+++ b/drivers/gpu/drm/i915/i915_gem_render_state.h
@@ -26,8 +26,15 @@

#include <linux/types.h>

+struct mod_value_info {
+ u32 offset;
+ u32 max_cnt;
+};
+
struct intel_renderstate_rodata {
const u32 *reloc;
+ const struct mod_value_info *mod_values;
+ const u32 mod_value_items;
const u32 *batch;
const u32 batch_items;
};
diff --git a/drivers/gpu/drm/i915/intel_renderstate.h b/drivers/gpu/drm/i915/intel_renderstate.h
index 5bd6985..1a80279 100644
--- a/drivers/gpu/drm/i915/intel_renderstate.h
+++ b/drivers/gpu/drm/i915/intel_renderstate.h
@@ -34,8 +34,12 @@ extern const struct intel_renderstate_rodata gen9_null_state;
#define RO_RENDERSTATE(_g) \
const struct intel_renderstate_rodata gen ## _g ## _null_state = { \
.reloc = gen ## _g ## _null_state_relocs, \
+ .mod_values = gen ## _g ## _mod_values, \
+ .mod_value_items = (sizeof(gen ## _g ## _mod_values) / \
+ sizeof(struct mod_value_info)), \
.batch = gen ## _g ## _null_state_batch, \
- .batch_items = sizeof(gen ## _g ## _null_state_batch)/4, \
+ .batch_items = (sizeof(gen ## _g ## _null_state_batch) / \
+ sizeof(u32)) \
}

#endif /* INTEL_RENDERSTATE_H */
diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen6.c b/drivers/gpu/drm/i915/intel_renderstate_gen6.c
index 11c8e7b..ef29069 100644
--- a/drivers/gpu/drm/i915/intel_renderstate_gen6.c
+++ b/drivers/gpu/drm/i915/intel_renderstate_gen6.c
@@ -34,6 +34,10 @@ static const u32 gen6_null_state_relocs[] = {
-1,
};

+static const struct mod_value_info gen6_mod_values[] = {
+ {-1, 0},
+};
+
static const u32 gen6_null_state_batch[] = {
0x69040000,
0x790d0001,
diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen7.c b/drivers/gpu/drm/i915/intel_renderstate_gen7.c
index 6551806..408e901 100644
--- a/drivers/gpu/drm/i915/intel_renderstate_gen7.c
+++ b/drivers/gpu/drm/i915/intel_renderstate_gen7.c
@@ -33,6 +33,10 @@ static const u32 gen7_null_state_relocs[] = {
-1,
};

+static const struct mod_value_info gen7_mod_values[] = {
+ {-1, 0},
+};
+
static const u32 gen7_null_state_batch[] = {
0x69040000,
0x61010008,
diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen8.c b/drivers/gpu/drm/i915/intel_renderstate_gen8.c
index 95288a3..d5b1383 100644
--- a/drivers/gpu/drm/i915/intel_renderstate_gen8.c
+++ b/drivers/gpu/drm/i915/intel_renderstate_gen8.c
@@ -33,6 +33,10 @@ static const u32 gen8_null_state_relocs[] = {
-1,
};

+static const struct mod_value_info gen8_mod_values[] = {
+ {-1, 0},
+};
+
static const u32 gen8_null_state_batch[] = {
0x7a000004,
0x01000000,
diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen9.c b/drivers/gpu/drm/i915/intel_renderstate_gen9.c
index 16a7ec2..7cb43a2 100644
--- a/drivers/gpu/drm/i915/intel_renderstate_gen9.c
+++ b/drivers/gpu/drm/i915/intel_renderstate_gen9.c
@@ -33,6 +33,10 @@ static const u32 gen9_null_state_relocs[] = {
-1,
};

+static const struct mod_value_info gen9_mod_values[] = {
+ {-1, 0},
+};
+
static const u32 gen9_null_state_batch[] = {
0x7a000004,
0x01000000,
--
1.9.1