[Intel-gfx] [RFCv3 3/3] drm/i915: Introduce per-platform PPAT configurations
Zhi Wang
zhi.a.wang at intel.com
Wed Aug 23 01:44:13 UTC 2017
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 at intel.com>
---
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
More information about the Intel-gfx
mailing list