Skip to content

Commit

Permalink
drm/i915: Invalidate the guc ggtt TLB upon insertion
Browse files Browse the repository at this point in the history
Move the GuC invalidation of its ggtt TLB to where we perform the ggtt
modification rather than proliferate it into all the callers of the
insert (which may or may not in fact have to do the insertion).

v2: Just do the guc invalidate unconditionally, (afaict) it has no impact
without the guc loaded on gen8+
v3: Conditionally invalidate the guc - just in case that register has
not been validated for other modes.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170112110050.25333-1-chris@chris-wilson.co.uk
  • Loading branch information
Chris Wilson committed Jan 12, 2017
1 parent 1d4258d commit 7c3f86b
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 40 deletions.
78 changes: 50 additions & 28 deletions drivers/gpu/drm/i915/i915_gem_gtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,30 @@ const struct i915_ggtt_view i915_ggtt_view_rotated = {
.type = I915_GGTT_VIEW_ROTATED,
};

static void gen6_ggtt_invalidate(struct drm_i915_private *dev_priv)
{
/* Note that as an uncached mmio write, this should flush the
* WCB of the writes into the GGTT before it triggers the invalidate.
*/
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
}

static void guc_ggtt_invalidate(struct drm_i915_private *dev_priv)
{
gen6_ggtt_invalidate(dev_priv);
I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
}

static void gmch_ggtt_invalidate(struct drm_i915_private *dev_priv)
{
intel_gtt_chipset_flush();
}

static inline void i915_ggtt_invalidate(struct drm_i915_private *i915)
{
i915->ggtt.invalidate(i915);
}

int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
int enable_ppgtt)
{
Expand Down Expand Up @@ -2307,16 +2331,6 @@ void i915_check_and_clear_faults(struct drm_i915_private *dev_priv)
POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
}

static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
{
if (INTEL_INFO(dev_priv)->gen < 6) {
intel_gtt_chipset_flush();
} else {
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
}
}

void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
Expand All @@ -2331,7 +2345,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv)

ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total);

i915_ggtt_flush(dev_priv);
i915_ggtt_invalidate(dev_priv);
}

int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
Expand Down Expand Up @@ -2370,23 +2384,20 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
enum i915_cache_level level,
u32 unused)
{
struct drm_i915_private *dev_priv = vm->i915;
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
gen8_pte_t __iomem *pte =
(gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
(offset >> PAGE_SHIFT);
(gen8_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT);

gen8_set_pte(pte, gen8_pte_encode(addr, level));

I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
ggtt->invalidate(vm->i915);
}

static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
struct sg_table *st,
uint64_t start,
enum i915_cache_level level, u32 unused)
{
struct drm_i915_private *dev_priv = vm->i915;
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
struct sgt_iter sgt_iter;
gen8_pte_t __iomem *gtt_entries;
Expand Down Expand Up @@ -2415,8 +2426,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
* want to flush the TLBs only after we're certain all the PTE updates
* have finished.
*/
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
ggtt->invalidate(vm->i915);
}

struct insert_entries {
Expand Down Expand Up @@ -2451,15 +2461,13 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm,
enum i915_cache_level level,
u32 flags)
{
struct drm_i915_private *dev_priv = vm->i915;
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
gen6_pte_t __iomem *pte =
(gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
(offset >> PAGE_SHIFT);
(gen6_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT);

iowrite32(vm->pte_encode(addr, level, flags), pte);

I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
ggtt->invalidate(vm->i915);
}

/*
Expand All @@ -2473,7 +2481,6 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
uint64_t start,
enum i915_cache_level level, u32 flags)
{
struct drm_i915_private *dev_priv = vm->i915;
struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
struct sgt_iter sgt_iter;
gen6_pte_t __iomem *gtt_entries;
Expand Down Expand Up @@ -2501,8 +2508,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
* want to flush the TLBs only after we're certain all the PTE updates
* have finished.
*/
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
ggtt->invalidate(vm->i915);
}

static void nop_clear_range(struct i915_address_space *vm,
Expand Down Expand Up @@ -3062,6 +3068,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
if (IS_CHERRYVIEW(dev_priv))
ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL;

ggtt->invalidate = gen6_ggtt_invalidate;

return ggtt_probe_common(ggtt, size);
}

Expand Down Expand Up @@ -3099,6 +3107,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt)
ggtt->base.unbind_vma = ggtt_unbind_vma;
ggtt->base.cleanup = gen6_gmch_remove;

ggtt->invalidate = gen6_ggtt_invalidate;

if (HAS_EDRAM(dev_priv))
ggtt->base.pte_encode = iris_pte_encode;
else if (IS_HASWELL(dev_priv))
Expand Down Expand Up @@ -3142,6 +3152,8 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
ggtt->base.unbind_vma = ggtt_unbind_vma;
ggtt->base.cleanup = i915_gmch_remove;

ggtt->invalidate = gmch_ggtt_invalidate;

if (unlikely(ggtt->do_idle_maps))
DRM_INFO("applying Ironlake quirks for intel_iommu\n");

Expand Down Expand Up @@ -3260,6 +3272,16 @@ int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
return 0;
}

void i915_ggtt_enable_guc(struct drm_i915_private *i915)
{
i915->ggtt.invalidate = guc_ggtt_invalidate;
}

void i915_ggtt_disable_guc(struct drm_i915_private *i915)
{
i915->ggtt.invalidate = gen6_ggtt_invalidate;
}

void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
Expand Down Expand Up @@ -3323,7 +3345,7 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
}
}

i915_ggtt_flush(dev_priv);
i915_ggtt_invalidate(dev_priv);
}

struct i915_vma *
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_gem_gtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ struct i915_ggtt {

/** "Graphics Stolen Memory" holds the global PTEs */
void __iomem *gsm;
void (*invalidate)(struct drm_i915_private *dev_priv);

bool do_idle_maps;

Expand Down Expand Up @@ -504,6 +505,8 @@ i915_vm_to_ggtt(struct i915_address_space *vm)
int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv);
int i915_ggtt_init_hw(struct drm_i915_private *dev_priv);
int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv);
void i915_ggtt_enable_guc(struct drm_i915_private *i915);
void i915_ggtt_disable_guc(struct drm_i915_private *i915);
int i915_gem_init_ggtt(struct drm_i915_private *dev_priv);
void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv);

Expand Down
3 changes: 0 additions & 3 deletions drivers/gpu/drm/i915/i915_guc_submission.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,9 +579,6 @@ static struct i915_vma *guc_allocate_vma(struct intel_guc *guc, u32 size)
goto err;
}

/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);

return vma;

err:
Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/drm/i915/intel_guc_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
return PTR_ERR(vma);
}

/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);

intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);

/* init WOPCM */
Expand Down Expand Up @@ -487,6 +484,9 @@ int intel_guc_setup(struct drm_i915_private *dev_priv)
guc_interrupts_release(dev_priv);
gen9_reset_guc_interrupts(dev_priv);

/* We need to notify the guc whenever we change the GGTT */
i915_ggtt_enable_guc(dev_priv);

guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;

DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
Expand Down Expand Up @@ -548,6 +548,7 @@ int intel_guc_setup(struct drm_i915_private *dev_priv)
guc_interrupts_release(dev_priv);
i915_guc_submission_disable(dev_priv);
i915_guc_submission_fini(dev_priv);
i915_ggtt_disable_guc(dev_priv);

/*
* We've failed to load the firmware :(
Expand Down
6 changes: 0 additions & 6 deletions drivers/gpu/drm/i915/intel_lrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,12 +811,6 @@ static int execlists_context_pin(struct intel_engine_cs *engine,

ce->state->obj->mm.dirty = true;

/* Invalidate GuC TLB. */
if (i915.enable_guc_submission) {
struct drm_i915_private *dev_priv = ctx->i915;
I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
}

i915_gem_context_get(ctx);
return 0;

Expand Down

0 comments on commit 7c3f86b

Please sign in to comment.