Skip to content

Commit

Permalink
drm/i915: keep track of used entries in MOCS table
Browse files Browse the repository at this point in the history
Instead of considering we have defined entries for any index in the
table, let's keep track of the ones we explicitly defined. This will
allow Gen 11 to have it's new table defined in which we have holes of
undefined entries.

Repeated comments about the meaning of undefined entries were removed
since they are overly verbose and copy-pasted in several functions: now
the definition is in the top only.

v2: add helper function to get the index (from Chris)

Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20190124000604.18861-6-lucas.demarchi@intel.com
  • Loading branch information
Lucas De Marchi committed Jan 25, 2019
1 parent 828f315 commit 1878fce
Showing 1 changed file with 78 additions and 33 deletions.
111 changes: 78 additions & 33 deletions drivers/gpu/drm/i915/intel_mocs.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
struct drm_i915_mocs_entry {
u32 control_value;
u16 l3cc_value;
u16 used;
};

struct drm_i915_mocs_table {
Expand Down Expand Up @@ -75,6 +76,7 @@ struct drm_i915_mocs_table {
[__idx] = { \
.control_value = __control_value, \
.l3cc_value = __l3cc_value, \
.used = 1, \
}

/*
Expand Down Expand Up @@ -187,6 +189,19 @@ static i915_reg_t mocs_register(enum intel_engine_id engine_id, int index)
}
}

/*
* Get control_value from MOCS entry taking into account when it's not used:
* I915_MOCS_PTE's value is returned in this case.
*/
static u32 get_entry_control(const struct drm_i915_mocs_table *table,
unsigned int index)
{
if (table->table[index].used)
return table->table[index].control_value;

return table->table[I915_MOCS_PTE].control_value;
}

/**
* intel_mocs_init_engine() - emit the mocs control table
* @engine: The engine for whom to emit the registers.
Expand All @@ -199,24 +214,25 @@ void intel_mocs_init_engine(struct intel_engine_cs *engine)
struct drm_i915_private *dev_priv = engine->i915;
struct drm_i915_mocs_table table;
unsigned int index;
u32 unused_value;

if (!get_mocs_settings(dev_priv, &table))
return;

GEM_BUG_ON(table.size > GEN9_NUM_MOCS_ENTRIES);

for (index = 0; index < table.size; index++)
I915_WRITE(mocs_register(engine->id, index),
table.table[index].control_value);
/* Set unused values to PTE */
unused_value = table.table[I915_MOCS_PTE].control_value;

for (index = 0; index < table.size; index++) {
u32 value = get_entry_control(&table, index);

/*
* Now set the unused entries to PTE. These entries are officially
* undefined and no contract for the contents and settings is given
* for these entries.
*/
I915_WRITE(mocs_register(engine->id, index), value);
}

/* All remaining entries are also unused */
for (; index < GEN9_NUM_MOCS_ENTRIES; index++)
I915_WRITE(mocs_register(engine->id, index),
table.table[I915_MOCS_PTE].control_value);
I915_WRITE(mocs_register(engine->id, index), unused_value);
}

/**
Expand All @@ -234,30 +250,32 @@ static int emit_mocs_control_table(struct i915_request *rq,
{
enum intel_engine_id engine = rq->engine->id;
unsigned int index;
u32 unused_value;
u32 *cs;

if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
return -ENODEV;

/* Set unused values to PTE */
unused_value = table->table[I915_MOCS_PTE].control_value;

cs = intel_ring_begin(rq, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
if (IS_ERR(cs))
return PTR_ERR(cs);

*cs++ = MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES);

for (index = 0; index < table->size; index++) {
u32 value = get_entry_control(table, index);

*cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
*cs++ = table->table[index].control_value;
*cs++ = value;
}

/*
* Now set the unused entries to PTE. These entries are officially
* undefined and no contract for the contents and settings is given
* for these entries.
*/
/* All remaining entries are also unused */
for (; index < GEN9_NUM_MOCS_ENTRIES; index++) {
*cs++ = i915_mmio_reg_offset(mocs_register(engine, index));
*cs++ = table->table[I915_MOCS_PTE].control_value;
*cs++ = unused_value;
}

*cs++ = MI_NOOP;
Expand All @@ -266,12 +284,24 @@ static int emit_mocs_control_table(struct i915_request *rq,
return 0;
}

/*
* Get l3cc_value from MOCS entry taking into account when it's not used:
* I915_MOCS_PTE's value is returned in this case.
*/
static u16 get_entry_l3cc(const struct drm_i915_mocs_table *table,
unsigned int index)
{
if (table->table[index].used)
return table->table[index].l3cc_value;

return table->table[I915_MOCS_PTE].l3cc_value;
}

static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table,
u16 low,
u16 high)
{
return table->table[low].l3cc_value |
table->table[high].l3cc_value << 16;
return low | high << 16;
}

/**
Expand All @@ -288,38 +318,43 @@ static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table,
static int emit_mocs_l3cc_table(struct i915_request *rq,
const struct drm_i915_mocs_table *table)
{
u16 unused_value;
unsigned int i;
u32 *cs;

if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
return -ENODEV;

/* Set unused values to PTE */
unused_value = table->table[I915_MOCS_PTE].l3cc_value;

cs = intel_ring_begin(rq, 2 + GEN9_NUM_MOCS_ENTRIES);
if (IS_ERR(cs))
return PTR_ERR(cs);

*cs++ = MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES / 2);

for (i = 0; i < table->size / 2; i++) {
u16 low = get_entry_l3cc(table, 2 * i);
u16 high = get_entry_l3cc(table, 2 * i + 1);

*cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
*cs++ = l3cc_combine(table, 2 * i, 2 * i + 1);
*cs++ = l3cc_combine(table, low, high);
}

/* Odd table size - 1 left over */
if (table->size & 0x01) {
/* Odd table size - 1 left over */
u16 low = get_entry_l3cc(table, 2 * i);

*cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
*cs++ = l3cc_combine(table, 2 * i, I915_MOCS_PTE);
*cs++ = l3cc_combine(table, low, unused_value);
i++;
}

/*
* Now set the unused entries to PTE. These entries are officially
* undefined and no contract for the contents and settings is given
* for these entries.
*/
/* All remaining entries are also unused */
for (; i < GEN9_NUM_MOCS_ENTRIES / 2; i++) {
*cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
*cs++ = l3cc_combine(table, I915_MOCS_PTE, I915_MOCS_PTE);
*cs++ = l3cc_combine(table, unused_value, unused_value);
}

*cs++ = MI_NOOP;
Expand All @@ -346,25 +381,35 @@ void intel_mocs_init_l3cc_table(struct drm_i915_private *dev_priv)
{
struct drm_i915_mocs_table table;
unsigned int i;
u16 unused_value;

if (!get_mocs_settings(dev_priv, &table))
return;

for (i = 0; i < table.size / 2; i++)
/* Set unused values to PTE */
unused_value = table.table[I915_MOCS_PTE].l3cc_value;

for (i = 0; i < table.size / 2; i++) {
u16 low = get_entry_l3cc(&table, 2 * i);
u16 high = get_entry_l3cc(&table, 2 * i + 1);

I915_WRITE(GEN9_LNCFCMOCS(i),
l3cc_combine(&table, 2 * i, 2 * i + 1));
l3cc_combine(&table, low, high));
}

/* Odd table size - 1 left over */
if (table.size & 0x01) {
u16 low = get_entry_l3cc(&table, 2 * i);

I915_WRITE(GEN9_LNCFCMOCS(i),
l3cc_combine(&table, 2 * i, I915_MOCS_PTE));
l3cc_combine(&table, low, unused_value));
i++;
}

/* Now set the rest of the table to PTE */
/* All remaining entries are also unused */
for (; i < (GEN9_NUM_MOCS_ENTRIES / 2); i++)
I915_WRITE(GEN9_LNCFCMOCS(i),
l3cc_combine(&table, I915_MOCS_PTE, I915_MOCS_PTE));
l3cc_combine(&table, unused_value, unused_value));
}

/**
Expand Down

0 comments on commit 1878fce

Please sign in to comment.