summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c')
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c134
1 files changed, 78 insertions, 56 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
index 7fb36b12fe7a..5eda98ebc1ae 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
@@ -1,30 +1,20 @@
+// SPDX-License-Identifier: MIT
/*
* Copyright © 2008-2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
*/
+#include <linux/highmem.h>
+
+#include <drm/drm_print.h>
+
+#include "display/intel_display.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_scatterlist.h"
#include "i915_pvinfo.h"
#include "i915_vgpu.h"
+#include "intel_gt_regs.h"
+#include "intel_mchbar_regs.h"
/**
* DOC: fence register handling
@@ -74,7 +64,7 @@ static void i965_write_fence_reg(struct i915_fence_reg *fence)
int fence_pitch_shift;
u64 val;
- if (INTEL_GEN(fence_to_i915(fence)) >= 6) {
+ if (GRAPHICS_VER(fence_to_i915(fence)) >= 6) {
fence_reg_lo = FENCE_REG_GEN6_LO(fence->id);
fence_reg_hi = FENCE_REG_GEN6_HI(fence->id);
fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT;
@@ -191,9 +181,9 @@ static void fence_write(struct i915_fence_reg *fence)
* and explicitly managed for internal users.
*/
- if (IS_GEN(i915, 2))
+ if (GRAPHICS_VER(i915) == 2)
i830_write_fence_reg(fence);
- else if (IS_GEN(i915, 3))
+ else if (GRAPHICS_VER(i915) == 3)
i915_write_fence_reg(fence);
else
i965_write_fence_reg(fence);
@@ -206,7 +196,7 @@ static void fence_write(struct i915_fence_reg *fence)
static bool gpu_uses_fence_registers(struct i915_fence_reg *fence)
{
- return INTEL_GEN(fence_to_i915(fence)) < 4;
+ return GRAPHICS_VER(fence_to_i915(fence)) < 4;
}
static int fence_update(struct i915_fence_reg *fence,
@@ -233,7 +223,8 @@ static int fence_update(struct i915_fence_reg *fence,
return ret;
}
- fence->start = vma->node.start;
+ GEM_BUG_ON(vma->fence_size > i915_vma_size(vma));
+ fence->start = i915_ggtt_offset(vma);
fence->size = vma->fence_size;
fence->stride = i915_gem_object_get_stride(vma->obj);
fence->tiling = i915_gem_object_get_tiling(vma->obj);
@@ -309,6 +300,7 @@ void i915_vma_revoke_fence(struct i915_vma *vma)
return;
GEM_BUG_ON(fence->vma != vma);
+ i915_active_wait(&fence->active);
GEM_BUG_ON(!i915_active_is_idle(&fence->active));
GEM_BUG_ON(atomic_read(&fence->pin_count));
@@ -316,17 +308,47 @@ void i915_vma_revoke_fence(struct i915_vma *vma)
WRITE_ONCE(fence->vma, NULL);
vma->fence = NULL;
- with_intel_runtime_pm_if_in_use(fence_to_uncore(fence)->rpm, wakeref)
+ /*
+ * Skip the write to HW if and only if the device is currently
+ * suspended.
+ *
+ * If the driver does not currently hold a wakeref (if_in_use == 0),
+ * the device may currently be runtime suspended, or it may be woken
+ * up before the suspend takes place. If the device is not suspended
+ * (powered down) and we skip clearing the fence register, the HW is
+ * left in an undefined state where we may end up with multiple
+ * registers overlapping.
+ */
+ with_intel_runtime_pm_if_active(fence_to_uncore(fence)->rpm, wakeref)
fence_write(fence);
}
+static bool fence_is_active(const struct i915_fence_reg *fence)
+{
+ return fence->vma && i915_vma_is_active(fence->vma);
+}
+
static struct i915_fence_reg *fence_find(struct i915_ggtt *ggtt)
{
- struct i915_fence_reg *fence;
+ struct intel_display *display = ggtt->vm.i915->display;
+ struct i915_fence_reg *active = NULL;
+ struct i915_fence_reg *fence, *fn;
- list_for_each_entry(fence, &ggtt->fence_list, link) {
+ list_for_each_entry_safe(fence, fn, &ggtt->fence_list, link) {
GEM_BUG_ON(fence->vma && fence->vma->fence != fence);
+ if (fence == active) /* now seen this fence twice */
+ active = ERR_PTR(-EAGAIN);
+
+ /* Prefer idle fences so we do not have to wait on the GPU */
+ if (active != ERR_PTR(-EAGAIN) && fence_is_active(fence)) {
+ if (!active)
+ active = fence;
+
+ list_move_tail(&fence->link, &ggtt->fence_list);
+ continue;
+ }
+
if (atomic_read(&fence->pin_count))
continue;
@@ -334,10 +356,10 @@ static struct i915_fence_reg *fence_find(struct i915_ggtt *ggtt)
}
/* Wait for completion of pending flips which consume fences */
- if (intel_has_pending_fb_unpin(ggtt->vm.i915))
+ if (intel_has_pending_fb_unpin(display))
return ERR_PTR(-EAGAIN);
- return ERR_PTR(-EDEADLK);
+ return ERR_PTR(-ENOBUFS);
}
int __i915_vma_pin_fence(struct i915_vma *vma)
@@ -399,7 +421,6 @@ out_unpin:
* For an untiled surface, this removes any existing fence.
*
* Returns:
- *
* 0 on success, negative error code on failure.
*/
int i915_vma_pin_fence(struct i915_vma *vma)
@@ -414,7 +435,6 @@ int i915_vma_pin_fence(struct i915_vma *vma)
* must keep the device awake whilst using the fence.
*/
assert_rpm_wakelock_held(vma->vm->gt->uncore->rpm);
- GEM_BUG_ON(!i915_vma_is_pinned(vma));
GEM_BUG_ON(!i915_vma_is_ggtt(vma));
err = mutex_lock_interruptible(&vma->vm->mutex);
@@ -558,7 +578,7 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
u32 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
u32 swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- if (INTEL_GEN(i915) >= 8 || IS_VALLEYVIEW(i915)) {
+ if (GRAPHICS_VER(i915) >= 8 || IS_VALLEYVIEW(i915)) {
/*
* On BDW+, swizzling is not used. We leave the CPU memory
* controller in charge of optimizing memory accesses without
@@ -568,7 +588,7 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
*/
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
- } else if (INTEL_GEN(i915) >= 6) {
+ } else if (GRAPHICS_VER(i915) >= 6) {
if (i915->preserve_bios_swizzle) {
if (intel_uncore_read(uncore, DISP_ARB_CTL) &
DISP_TILE_SURFACE_SWIZZLING) {
@@ -580,6 +600,7 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
}
} else {
u32 dimm_c0, dimm_c1;
+
dimm_c0 = intel_uncore_read(uncore, MAD_DIMM_C0);
dimm_c1 = intel_uncore_read(uncore, MAD_DIMM_C1);
dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
@@ -599,14 +620,14 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
}
}
- } else if (IS_GEN(i915, 5)) {
+ } else if (GRAPHICS_VER(i915) == 5) {
/*
* On Ironlake whatever DRAM config, GPU always do
* same swizzling setup.
*/
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9;
- } else if (IS_GEN(i915, 2)) {
+ } else if (GRAPHICS_VER(i915) == 2) {
/*
* As far as we know, the 865 doesn't have these bit 6
* swizzling issues.
@@ -641,8 +662,8 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
* banks of memory are paired and unswizzled on the
* uneven portion, so leave that as unknown.
*/
- if (intel_uncore_read(uncore, C0DRB3) ==
- intel_uncore_read(uncore, C1DRB3)) {
+ if (intel_uncore_read16(uncore, C0DRB3_BW) ==
+ intel_uncore_read16(uncore, C1DRB3_BW)) {
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
swizzle_y = I915_BIT_6_SWIZZLE_9;
}
@@ -685,7 +706,7 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
}
/* check for L-shaped memory aka modified enhanced addressing */
- if (IS_GEN(i915, 4) &&
+ if (GRAPHICS_VER(i915) == 4 &&
!(intel_uncore_read(uncore, DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) {
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
@@ -711,13 +732,13 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
* bit17 dependent, and so we need to also prevent the pages
* from being moved.
*/
- i915->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
+ i915->gem_quirks |= GEM_QUIRK_PIN_SWIZZLED_PAGES;
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
}
- i915->ggtt.bit_6_swizzle_x = swizzle_x;
- i915->ggtt.bit_6_swizzle_y = swizzle_y;
+ to_gt(i915)->ggtt->bit_6_swizzle_x = swizzle_x;
+ to_gt(i915)->ggtt->bit_6_swizzle_y = swizzle_y;
}
/*
@@ -731,7 +752,7 @@ static void swizzle_page(struct page *page)
char *vaddr;
int i;
- vaddr = kmap(page);
+ vaddr = kmap_local_page(page);
for (i = 0; i < PAGE_SIZE; i += 128) {
memcpy(temp, &vaddr[i], 64);
@@ -739,7 +760,7 @@ static void swizzle_page(struct page *page)
memcpy(&vaddr[i + 64], temp, 64);
}
- kunmap(page);
+ kunmap_local(vaddr);
}
/**
@@ -769,10 +790,12 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
i = 0;
for_each_sgt_page(page, sgt_iter, pages) {
char new_bit_17 = page_to_phys(page) >> 17;
+
if ((new_bit_17 & 0x1) != (test_bit(i, obj->bit_17) != 0)) {
swizzle_page(page);
set_page_dirty(page);
}
+
i++;
}
}
@@ -798,8 +821,8 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
if (obj->bit_17 == NULL) {
obj->bit_17 = bitmap_zalloc(page_count, GFP_KERNEL);
if (obj->bit_17 == NULL) {
- DRM_ERROR("Failed to allocate memory for bit 17 "
- "record\n");
+ drm_err(obj->base.dev,
+ "Failed to allocate memory for bit 17 record\n");
return;
}
}
@@ -824,16 +847,15 @@ void intel_ggtt_init_fences(struct i915_ggtt *ggtt)
INIT_LIST_HEAD(&ggtt->fence_list);
INIT_LIST_HEAD(&ggtt->userfault_list);
- intel_wakeref_auto_init(&ggtt->userfault_wakeref, uncore->rpm);
detect_bit_6_swizzle(ggtt);
if (!i915_ggtt_has_aperture(ggtt))
num_fences = 0;
- else if (INTEL_GEN(i915) >= 7 &&
+ else if (GRAPHICS_VER(i915) >= 7 &&
!(IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)))
num_fences = 32;
- else if (INTEL_GEN(i915) >= 4 ||
+ else if (GRAPHICS_VER(i915) >= 4 ||
IS_I945G(i915) || IS_I945GM(i915) ||
IS_G33(i915) || IS_PINEVIEW(i915))
num_fences = 16;
@@ -853,7 +875,7 @@ void intel_ggtt_init_fences(struct i915_ggtt *ggtt)
for (i = 0; i < num_fences; i++) {
struct i915_fence_reg *fence = &ggtt->fence_regs[i];
- i915_active_init(&fence->active, NULL, NULL);
+ i915_active_init(&fence->active, NULL, NULL, 0);
fence->ggtt = ggtt;
fence->id = i;
list_add_tail(&fence->link, &ggtt->fence_list);
@@ -881,29 +903,29 @@ void intel_gt_init_swizzling(struct intel_gt *gt)
struct drm_i915_private *i915 = gt->i915;
struct intel_uncore *uncore = gt->uncore;
- if (INTEL_GEN(i915) < 5 ||
- i915->ggtt.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE)
+ if (GRAPHICS_VER(i915) < 5 ||
+ to_gt(i915)->ggtt->bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE)
return;
intel_uncore_rmw(uncore, DISP_ARB_CTL, 0, DISP_TILE_SURFACE_SWIZZLING);
- if (IS_GEN(i915, 5))
+ if (GRAPHICS_VER(i915) == 5)
return;
intel_uncore_rmw(uncore, TILECTL, 0, TILECTL_SWZCTL);
- if (IS_GEN(i915, 6))
+ if (GRAPHICS_VER(i915) == 6)
intel_uncore_write(uncore,
ARB_MODE,
_MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
- else if (IS_GEN(i915, 7))
+ else if (GRAPHICS_VER(i915) == 7)
intel_uncore_write(uncore,
ARB_MODE,
_MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
- else if (IS_GEN(i915, 8))
+ else if (GRAPHICS_VER(i915) == 8)
intel_uncore_write(uncore,
GAMTARBMODE,
_MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW));
else
- MISSING_CASE(INTEL_GEN(i915));
+ MISSING_CASE(GRAPHICS_VER(i915));
}