diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c')
| -rw-r--r-- | drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 134 |
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)); } |
