The previous static PPAT configuration for each platform is kept unchanged and now configured through intel_ppat_reserve(). Also the PPAT feature of each platform is described in intel PPAT instance during the initialization and related callbacks which supports the PPAT management framework will be hooked. Signed-off-by: Zhi Wang <zhi.a.wang@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_gem_gtt.c | 145 ++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2a521b6..d103ea4 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2857,41 +2857,92 @@ void intel_ppat_put(struct intel_ppat_entry *entry) kref_put(&entry->ref_count, put_ppat); } -static void cnl_setup_private_ppat(struct drm_i915_private *dev_priv) +static void cnl_private_pat_update(struct drm_i915_private *dev_priv) { + struct intel_ppat *ppat = &dev_priv->ppat; + int i; + + for (i = 0; i < ppat->max_entries; i++) + I915_WRITE(GEN10_PAT_INDEX(i), ppat->entries[i].value); +} + +static void bdw_private_pat_update(struct drm_i915_private *dev_priv) +{ + struct intel_ppat *ppat = &dev_priv->ppat; + u64 pat = 0; + int i; + + for (i = 0; i < ppat->max_entries; i++) + pat |= GEN8_PPAT(i, ppat->entries[i].value); + + I915_WRITE(GEN8_PRIVATE_PAT_LO, pat); + I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); +} + +#define gen8_pat_ca(v) ((v) & 0x3) +#define gen8_pat_tc(v) (((v) >> 2) & 0x3) +#define gen8_pat_age(v) (((v) >> 4) & 0x3) + +static unsigned int bdw_private_pat_match(u8 src, u8 dst) +{ + unsigned int score = 0; + + /* Cache attribute has to be matched. */ + if (gen8_pat_ca(src) != gen8_pat_ca(dst)) + return 0; + + if (gen8_pat_age(src) == gen8_pat_age(dst)) + score += 1; + + if (gen8_pat_tc(src) == gen8_pat_tc(dst)) + score += 2; + + if (score == 3) + return ~0; + + return score; +} + +#define chv_get_snoop(v) (((v) >> 6) & 0x1) + +static unsigned int chv_private_pat_match(u8 src, u8 dst) +{ + if (chv_get_snoop(src) == chv_get_snoop(dst)) + return ~0; + + return 0; +} + +static void cnl_setup_private_ppat(struct intel_ppat *ppat) +{ + ppat->max_entries = 8; + ppat->update = cnl_private_pat_update; + ppat->match = bdw_private_pat_match; + ppat->dummy_value = GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3); + /* XXX: spec is unclear if this is still needed for CNL+ */ if (!USES_PPGTT(dev_priv)) { - I915_WRITE(GEN10_PAT_INDEX(0), GEN8_PPAT_UC); + intel_ppat_reserve(ppat, 0, GEN8_PPAT_UC); return; } - I915_WRITE(GEN10_PAT_INDEX(0), GEN8_PPAT_WB | GEN8_PPAT_LLC); - I915_WRITE(GEN10_PAT_INDEX(1), GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); - I915_WRITE(GEN10_PAT_INDEX(2), GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); - I915_WRITE(GEN10_PAT_INDEX(3), GEN8_PPAT_UC); - I915_WRITE(GEN10_PAT_INDEX(4), GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)); - I915_WRITE(GEN10_PAT_INDEX(5), GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)); - I915_WRITE(GEN10_PAT_INDEX(6), GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)); - I915_WRITE(GEN10_PAT_INDEX(7), GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); + intel_ppat_reserve(ppat, 0, GEN8_PPAT_WB | GEN8_PPAT_LLC); + intel_ppat_reserve(ppat, 1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); + intel_ppat_reserve(ppat, 2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); + intel_ppat_reserve(ppat, 3, GEN8_PPAT_UC); } /* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability * bits. When using advanced contexts each context stores its own PAT, but * writing this data shouldn't be harmful even in those cases. */ -static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv) +static void bdw_setup_private_ppat(struct intel_ppat *ppat) { - u64 pat; + ppat->max_entries = 8; + ppat->update = bdw_private_pat_update; + ppat->match = bdw_private_pat_match; + ppat->dummy_value = GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3); - pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC) | /* for normal objects, no eLLC */ - GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) | /* for something pointing to ptes? */ - GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) | /* for scanout with eLLC */ - GEN8_PPAT(3, GEN8_PPAT_UC) | /* Uncached objects, mostly for scanout */ - GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) | - GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) | - GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) | - GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); - - if (!USES_PPGTT(dev_priv)) + if (!USES_PPGTT(dev_priv)) { /* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry, * so RTL will always use the value corresponding to * pat_sel = 000". @@ -2905,17 +2956,22 @@ static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv) * So we can still hold onto all our assumptions wrt cpu * clflushing on LLC machines. */ - pat = GEN8_PPAT(0, GEN8_PPAT_UC); + intel_ppat_reserve(ppat, 0, GEN8_PPAT_UC); + return; + } - /* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b - * write would work. */ - I915_WRITE(GEN8_PRIVATE_PAT_LO, pat); - I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); + intel_ppat_reserve(ppat, 0, GEN8_PPAT_WB | GEN8_PPAT_LLC); /* for normal objects, no eLLC */ + intel_ppat_reserve(ppat, 1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); /* for something pointing to ptes? */ + intel_ppat_reserve(ppat, 2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); /* for scanout with eLLC */ + intel_ppat_reserve(ppat, 3, GEN8_PPAT_UC); /* Uncached objects, mostly for scanout */ } -static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) +static void chv_setup_private_ppat(struct intel_ppat *ppat) { - u64 pat; + ppat->max_entries = 8; + ppat->update = bdw_private_pat_update; + ppat->match = chv_private_pat_match; + ppat->dummy_value = CHV_PPAT_SNOOP; /* * Map WB on BDW to snooped on CHV. @@ -2935,17 +2991,11 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) * Which means we must set the snoop bit in PAT entry 0 * in order to keep the global status page working. */ - pat = GEN8_PPAT(0, CHV_PPAT_SNOOP) | - GEN8_PPAT(1, 0) | - GEN8_PPAT(2, 0) | - GEN8_PPAT(3, 0) | - GEN8_PPAT(4, CHV_PPAT_SNOOP) | - GEN8_PPAT(5, CHV_PPAT_SNOOP) | - GEN8_PPAT(6, CHV_PPAT_SNOOP) | - GEN8_PPAT(7, CHV_PPAT_SNOOP); - I915_WRITE(GEN8_PRIVATE_PAT_LO, pat); - I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); + intel_ppat_reserve(ppat, 0, CHV_PPAT_SNOOP); + intel_ppat_reserve(ppat, 1, 0); + intel_ppat_reserve(ppat, 2, 0); + intel_ppat_reserve(ppat, 3, 0); } static void gen6_gmch_remove(struct i915_address_space *vm) @@ -2963,20 +3013,23 @@ static void setup_private_pat(struct drm_i915_private *dev_priv) ppat->dev_priv = dev_priv; + /* Load per-platform PPAT configurations */ if (INTEL_GEN(dev_priv) >= 10) - cnl_setup_private_ppat(dev_priv); + cnl_setup_private_ppat(ppat); else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) - chv_setup_private_ppat(dev_priv); + chv_setup_private_ppat(ppat); else - bdw_setup_private_ppat(dev_priv); + bdw_setup_private_ppat(ppat); GEM_BUG_ON(ppat->max_entries > INTEL_MAX_PPAT_ENTRIES); + /* Fill unused PPAT entries with dummy PPAT value */ for_each_clear_bit(i, ppat->reserved, ppat->max_entries) { ppat->entries[i].value = ppat->dummy_value; ppat->entries[i].ppat = ppat; } + /* Write the HW */ ppat->update(dev_priv); } @@ -3291,13 +3344,7 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) ggtt->base.closed = false; if (INTEL_GEN(dev_priv) >= 8) { - if (INTEL_GEN(dev_priv) >= 10) - cnl_setup_private_ppat(dev_priv); - else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) - chv_setup_private_ppat(dev_priv); - else - bdw_setup_private_ppat(dev_priv); - + dev_priv->ppat.update(dev_priv); return; } -- 2.7.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx