Commit 7c3f86b6 authored by Chris Wilson's avatar Chris Wilson

drm/i915: Invalidate the guc ggtt TLB upon insertion

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170112110050.25333-1-chris@chris-wilson.co.uk
parent 1d4258db
...@@ -110,6 +110,30 @@ const struct i915_ggtt_view i915_ggtt_view_rotated = { ...@@ -110,6 +110,30 @@ const struct i915_ggtt_view i915_ggtt_view_rotated = {
.type = 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 intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
int enable_ppgtt) int enable_ppgtt)
{ {
...@@ -2307,16 +2331,6 @@ void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) ...@@ -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])); 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) void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv)
{ {
struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_ggtt *ggtt = &dev_priv->ggtt;
...@@ -2331,7 +2345,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv) ...@@ -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); 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, int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
...@@ -2370,15 +2384,13 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, ...@@ -2370,15 +2384,13 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
enum i915_cache_level level, enum i915_cache_level level,
u32 unused) 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 *pte =
(gen8_pte_t __iomem *)dev_priv->ggtt.gsm + (gen8_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT);
(offset >> PAGE_SHIFT);
gen8_set_pte(pte, gen8_pte_encode(addr, level)); gen8_set_pte(pte, gen8_pte_encode(addr, level));
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); ggtt->invalidate(vm->i915);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
} }
static void gen8_ggtt_insert_entries(struct i915_address_space *vm, static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
...@@ -2386,7 +2398,6 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -2386,7 +2398,6 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
uint64_t start, uint64_t start,
enum i915_cache_level level, u32 unused) 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 i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
struct sgt_iter sgt_iter; struct sgt_iter sgt_iter;
gen8_pte_t __iomem *gtt_entries; gen8_pte_t __iomem *gtt_entries;
...@@ -2415,8 +2426,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -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 * want to flush the TLBs only after we're certain all the PTE updates
* have finished. * have finished.
*/ */
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); ggtt->invalidate(vm->i915);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
} }
struct insert_entries { struct insert_entries {
...@@ -2451,15 +2461,13 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm, ...@@ -2451,15 +2461,13 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm,
enum i915_cache_level level, enum i915_cache_level level,
u32 flags) 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 *pte =
(gen6_pte_t __iomem *)dev_priv->ggtt.gsm + (gen6_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT);
(offset >> PAGE_SHIFT);
iowrite32(vm->pte_encode(addr, level, flags), pte); iowrite32(vm->pte_encode(addr, level, flags), pte);
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); ggtt->invalidate(vm->i915);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
} }
/* /*
...@@ -2473,7 +2481,6 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -2473,7 +2481,6 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
uint64_t start, uint64_t start,
enum i915_cache_level level, u32 flags) 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 i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
struct sgt_iter sgt_iter; struct sgt_iter sgt_iter;
gen6_pte_t __iomem *gtt_entries; gen6_pte_t __iomem *gtt_entries;
...@@ -2501,8 +2508,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, ...@@ -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 * want to flush the TLBs only after we're certain all the PTE updates
* have finished. * have finished.
*/ */
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); ggtt->invalidate(vm->i915);
POSTING_READ(GFX_FLSH_CNTL_GEN6);
} }
static void nop_clear_range(struct i915_address_space *vm, static void nop_clear_range(struct i915_address_space *vm,
...@@ -3062,6 +3068,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ...@@ -3062,6 +3068,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
if (IS_CHERRYVIEW(dev_priv)) if (IS_CHERRYVIEW(dev_priv))
ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL; ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL;
ggtt->invalidate = gen6_ggtt_invalidate;
return ggtt_probe_common(ggtt, size); return ggtt_probe_common(ggtt, size);
} }
...@@ -3099,6 +3107,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) ...@@ -3099,6 +3107,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt)
ggtt->base.unbind_vma = ggtt_unbind_vma; ggtt->base.unbind_vma = ggtt_unbind_vma;
ggtt->base.cleanup = gen6_gmch_remove; ggtt->base.cleanup = gen6_gmch_remove;
ggtt->invalidate = gen6_ggtt_invalidate;
if (HAS_EDRAM(dev_priv)) if (HAS_EDRAM(dev_priv))
ggtt->base.pte_encode = iris_pte_encode; ggtt->base.pte_encode = iris_pte_encode;
else if (IS_HASWELL(dev_priv)) else if (IS_HASWELL(dev_priv))
...@@ -3142,6 +3152,8 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt) ...@@ -3142,6 +3152,8 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
ggtt->base.unbind_vma = ggtt_unbind_vma; ggtt->base.unbind_vma = ggtt_unbind_vma;
ggtt->base.cleanup = i915_gmch_remove; ggtt->base.cleanup = i915_gmch_remove;
ggtt->invalidate = gmch_ggtt_invalidate;
if (unlikely(ggtt->do_idle_maps)) if (unlikely(ggtt->do_idle_maps))
DRM_INFO("applying Ironlake quirks for intel_iommu\n"); DRM_INFO("applying Ironlake quirks for intel_iommu\n");
...@@ -3260,6 +3272,16 @@ int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv) ...@@ -3260,6 +3272,16 @@ int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv)
return 0; 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) void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
{ {
struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_ggtt *ggtt = &dev_priv->ggtt;
...@@ -3323,7 +3345,7 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) ...@@ -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 * struct i915_vma *
......
...@@ -336,6 +336,7 @@ struct i915_ggtt { ...@@ -336,6 +336,7 @@ struct i915_ggtt {
/** "Graphics Stolen Memory" holds the global PTEs */ /** "Graphics Stolen Memory" holds the global PTEs */
void __iomem *gsm; void __iomem *gsm;
void (*invalidate)(struct drm_i915_private *dev_priv);
bool do_idle_maps; bool do_idle_maps;
...@@ -504,6 +505,8 @@ i915_vm_to_ggtt(struct i915_address_space *vm) ...@@ -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_probe_hw(struct drm_i915_private *dev_priv);
int i915_ggtt_init_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); 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); int i915_gem_init_ggtt(struct drm_i915_private *dev_priv);
void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv); void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv);
......
...@@ -579,9 +579,6 @@ static struct i915_vma *guc_allocate_vma(struct intel_guc *guc, u32 size) ...@@ -579,9 +579,6 @@ static struct i915_vma *guc_allocate_vma(struct intel_guc *guc, u32 size)
goto err; goto err;
} }
/* Invalidate GuC TLB to let GuC take the latest updates to GTT. */
I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE);
return vma; return vma;
err: err:
......
...@@ -367,9 +367,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) ...@@ -367,9 +367,6 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
return PTR_ERR(vma); 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); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
/* init WOPCM */ /* init WOPCM */
...@@ -487,6 +484,9 @@ int intel_guc_setup(struct drm_i915_private *dev_priv) ...@@ -487,6 +484,9 @@ int intel_guc_setup(struct drm_i915_private *dev_priv)
guc_interrupts_release(dev_priv); guc_interrupts_release(dev_priv);
gen9_reset_guc_interrupts(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; guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
...@@ -548,6 +548,7 @@ int intel_guc_setup(struct drm_i915_private *dev_priv) ...@@ -548,6 +548,7 @@ int intel_guc_setup(struct drm_i915_private *dev_priv)
guc_interrupts_release(dev_priv); guc_interrupts_release(dev_priv);
i915_guc_submission_disable(dev_priv); i915_guc_submission_disable(dev_priv);
i915_guc_submission_fini(dev_priv); i915_guc_submission_fini(dev_priv);
i915_ggtt_disable_guc(dev_priv);
/* /*
* We've failed to load the firmware :( * We've failed to load the firmware :(
......
...@@ -811,12 +811,6 @@ static int execlists_context_pin(struct intel_engine_cs *engine, ...@@ -811,12 +811,6 @@ static int execlists_context_pin(struct intel_engine_cs *engine,
ce->state->obj->mm.dirty = true; 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); i915_gem_context_get(ctx);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment