| From f1e1c2129b79cfdaf07bca37c5a10569fe021abe Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> |
| Date: Thu, 5 Jun 2014 20:02:59 +0300 |
| Subject: drm/i915: Don't clobber the GTT when it's within stolen memory |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| |
| commit f1e1c2129b79cfdaf07bca37c5a10569fe021abe upstream. |
| |
| On most gen2-4 platforms the GTT can be (or maybe always is?) |
| inside the stolen memory region. If that's the case, reduce the |
| size of the stolen memory appropriately to make make sure we |
| don't clobber the GTT. |
| |
| v2: Deal with gen4 36 bit physical address |
| |
| Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80151 |
| Acked-by: Chris Wilson <chris@chris-wilson.co.uk> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/i915/i915_gem_stolen.c | 44 +++++++++++++++++++++++++++++++++ |
| drivers/gpu/drm/i915/i915_reg.h | 3 ++ |
| 2 files changed, 47 insertions(+) |
| |
| --- a/drivers/gpu/drm/i915/i915_gem_stolen.c |
| +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c |
| @@ -74,6 +74,50 @@ static unsigned long i915_stolen_to_phys |
| if (base == 0) |
| return 0; |
| |
| + /* make sure we don't clobber the GTT if it's within stolen memory */ |
| + if (INTEL_INFO(dev)->gen <= 4 && !IS_G33(dev) && !IS_G4X(dev)) { |
| + struct { |
| + u32 start, end; |
| + } stolen[2] = { |
| + { .start = base, .end = base + dev_priv->gtt.stolen_size, }, |
| + { .start = base, .end = base + dev_priv->gtt.stolen_size, }, |
| + }; |
| + u64 gtt_start, gtt_end; |
| + |
| + gtt_start = I915_READ(PGTBL_CTL); |
| + if (IS_GEN4(dev)) |
| + gtt_start = (gtt_start & PGTBL_ADDRESS_LO_MASK) | |
| + (gtt_start & PGTBL_ADDRESS_HI_MASK) << 28; |
| + else |
| + gtt_start &= PGTBL_ADDRESS_LO_MASK; |
| + gtt_end = gtt_start + gtt_total_entries(dev_priv->gtt) * 4; |
| + |
| + if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end) |
| + stolen[0].end = gtt_start; |
| + if (gtt_end > stolen[1].start && gtt_end <= stolen[1].end) |
| + stolen[1].start = gtt_end; |
| + |
| + /* pick the larger of the two chunks */ |
| + if (stolen[0].end - stolen[0].start > |
| + stolen[1].end - stolen[1].start) { |
| + base = stolen[0].start; |
| + dev_priv->gtt.stolen_size = stolen[0].end - stolen[0].start; |
| + } else { |
| + base = stolen[1].start; |
| + dev_priv->gtt.stolen_size = stolen[1].end - stolen[1].start; |
| + } |
| + |
| + if (stolen[0].start != stolen[1].start || |
| + stolen[0].end != stolen[1].end) { |
| + DRM_DEBUG_KMS("GTT within stolen memory at 0x%llx-0x%llx\n", |
| + (unsigned long long) gtt_start, |
| + (unsigned long long) gtt_end - 1); |
| + DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n", |
| + base, base + (u32) dev_priv->gtt.stolen_size - 1); |
| + } |
| + } |
| + |
| + |
| /* Verify that nothing else uses this physical address. Stolen |
| * memory should be reserved by the BIOS and hidden from the |
| * kernel. So if the region is already marked as busy, something |
| --- a/drivers/gpu/drm/i915/i915_reg.h |
| +++ b/drivers/gpu/drm/i915/i915_reg.h |
| @@ -631,6 +631,9 @@ |
| /* |
| * Instruction and interrupt control regs |
| */ |
| +#define PGTBL_CTL 0x02020 |
| +#define PGTBL_ADDRESS_LO_MASK 0xfffff000 /* bits [31:12] */ |
| +#define PGTBL_ADDRESS_HI_MASK 0x000000f0 /* bits [35:32] (gen4) */ |
| #define PGTBL_ER 0x02024 |
| #define RENDER_RING_BASE 0x02000 |
| #define BSD_RING_BASE 0x04000 |