diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 101 |
1 files changed, 49 insertions, 52 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4200c32407ec..d9e2208cfe98 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1880,6 +1880,10 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, | |||
1880 | u32 seqno = intel_ring_get_seqno(ring); | 1880 | u32 seqno = intel_ring_get_seqno(ring); |
1881 | 1881 | ||
1882 | BUG_ON(ring == NULL); | 1882 | BUG_ON(ring == NULL); |
1883 | if (obj->ring != ring && obj->last_write_seqno) { | ||
1884 | /* Keep the seqno relative to the current ring */ | ||
1885 | obj->last_write_seqno = seqno; | ||
1886 | } | ||
1883 | obj->ring = ring; | 1887 | obj->ring = ring; |
1884 | 1888 | ||
1885 | /* Add a reference if we're newly entering the active list. */ | 1889 | /* Add a reference if we're newly entering the active list. */ |
@@ -2254,7 +2258,17 @@ void i915_gem_restore_fences(struct drm_device *dev) | |||
2254 | 2258 | ||
2255 | for (i = 0; i < dev_priv->num_fence_regs; i++) { | 2259 | for (i = 0; i < dev_priv->num_fence_regs; i++) { |
2256 | struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; | 2260 | struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; |
2257 | i915_gem_write_fence(dev, i, reg->obj); | 2261 | |
2262 | /* | ||
2263 | * Commit delayed tiling changes if we have an object still | ||
2264 | * attached to the fence, otherwise just clear the fence. | ||
2265 | */ | ||
2266 | if (reg->obj) { | ||
2267 | i915_gem_object_update_fence(reg->obj, reg, | ||
2268 | reg->obj->tiling_mode); | ||
2269 | } else { | ||
2270 | i915_gem_write_fence(dev, i, NULL); | ||
2271 | } | ||
2258 | } | 2272 | } |
2259 | } | 2273 | } |
2260 | 2274 | ||
@@ -2653,7 +2667,6 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, | |||
2653 | drm_i915_private_t *dev_priv = dev->dev_private; | 2667 | drm_i915_private_t *dev_priv = dev->dev_private; |
2654 | int fence_reg; | 2668 | int fence_reg; |
2655 | int fence_pitch_shift; | 2669 | int fence_pitch_shift; |
2656 | uint64_t val; | ||
2657 | 2670 | ||
2658 | if (INTEL_INFO(dev)->gen >= 6) { | 2671 | if (INTEL_INFO(dev)->gen >= 6) { |
2659 | fence_reg = FENCE_REG_SANDYBRIDGE_0; | 2672 | fence_reg = FENCE_REG_SANDYBRIDGE_0; |
@@ -2663,8 +2676,23 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, | |||
2663 | fence_pitch_shift = I965_FENCE_PITCH_SHIFT; | 2676 | fence_pitch_shift = I965_FENCE_PITCH_SHIFT; |
2664 | } | 2677 | } |
2665 | 2678 | ||
2679 | fence_reg += reg * 8; | ||
2680 | |||
2681 | /* To w/a incoherency with non-atomic 64-bit register updates, | ||
2682 | * we split the 64-bit update into two 32-bit writes. In order | ||
2683 | * for a partial fence not to be evaluated between writes, we | ||
2684 | * precede the update with write to turn off the fence register, | ||
2685 | * and only enable the fence as the last step. | ||
2686 | * | ||
2687 | * For extra levels of paranoia, we make sure each step lands | ||
2688 | * before applying the next step. | ||
2689 | */ | ||
2690 | I915_WRITE(fence_reg, 0); | ||
2691 | POSTING_READ(fence_reg); | ||
2692 | |||
2666 | if (obj) { | 2693 | if (obj) { |
2667 | u32 size = obj->gtt_space->size; | 2694 | u32 size = obj->gtt_space->size; |
2695 | uint64_t val; | ||
2668 | 2696 | ||
2669 | val = (uint64_t)((obj->gtt_offset + size - 4096) & | 2697 | val = (uint64_t)((obj->gtt_offset + size - 4096) & |
2670 | 0xfffff000) << 32; | 2698 | 0xfffff000) << 32; |
@@ -2673,12 +2701,16 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, | |||
2673 | if (obj->tiling_mode == I915_TILING_Y) | 2701 | if (obj->tiling_mode == I915_TILING_Y) |
2674 | val |= 1 << I965_FENCE_TILING_Y_SHIFT; | 2702 | val |= 1 << I965_FENCE_TILING_Y_SHIFT; |
2675 | val |= I965_FENCE_REG_VALID; | 2703 | val |= I965_FENCE_REG_VALID; |
2676 | } else | ||
2677 | val = 0; | ||
2678 | 2704 | ||
2679 | fence_reg += reg * 8; | 2705 | I915_WRITE(fence_reg + 4, val >> 32); |
2680 | I915_WRITE64(fence_reg, val); | 2706 | POSTING_READ(fence_reg + 4); |
2681 | POSTING_READ(fence_reg); | 2707 | |
2708 | I915_WRITE(fence_reg + 0, val); | ||
2709 | POSTING_READ(fence_reg); | ||
2710 | } else { | ||
2711 | I915_WRITE(fence_reg + 4, 0); | ||
2712 | POSTING_READ(fence_reg + 4); | ||
2713 | } | ||
2682 | } | 2714 | } |
2683 | 2715 | ||
2684 | static void i915_write_fence_reg(struct drm_device *dev, int reg, | 2716 | static void i915_write_fence_reg(struct drm_device *dev, int reg, |
@@ -2773,6 +2805,10 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg, | |||
2773 | if (i915_gem_object_needs_mb(dev_priv->fence_regs[reg].obj)) | 2805 | if (i915_gem_object_needs_mb(dev_priv->fence_regs[reg].obj)) |
2774 | mb(); | 2806 | mb(); |
2775 | 2807 | ||
2808 | WARN(obj && (!obj->stride || !obj->tiling_mode), | ||
2809 | "bogus fence setup with stride: 0x%x, tiling mode: %i\n", | ||
2810 | obj->stride, obj->tiling_mode); | ||
2811 | |||
2776 | switch (INTEL_INFO(dev)->gen) { | 2812 | switch (INTEL_INFO(dev)->gen) { |
2777 | case 7: | 2813 | case 7: |
2778 | case 6: | 2814 | case 6: |
@@ -2796,56 +2832,17 @@ static inline int fence_number(struct drm_i915_private *dev_priv, | |||
2796 | return fence - dev_priv->fence_regs; | 2832 | return fence - dev_priv->fence_regs; |
2797 | } | 2833 | } |
2798 | 2834 | ||
2799 | struct write_fence { | ||
2800 | struct drm_device *dev; | ||
2801 | struct drm_i915_gem_object *obj; | ||
2802 | int fence; | ||
2803 | }; | ||
2804 | |||
2805 | static void i915_gem_write_fence__ipi(void *data) | ||
2806 | { | ||
2807 | struct write_fence *args = data; | ||
2808 | |||
2809 | /* Required for SNB+ with LLC */ | ||
2810 | wbinvd(); | ||
2811 | |||
2812 | /* Required for VLV */ | ||
2813 | i915_gem_write_fence(args->dev, args->fence, args->obj); | ||
2814 | } | ||
2815 | |||
2816 | static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, | 2835 | static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, |
2817 | struct drm_i915_fence_reg *fence, | 2836 | struct drm_i915_fence_reg *fence, |
2818 | bool enable) | 2837 | bool enable) |
2819 | { | 2838 | { |
2820 | struct drm_i915_private *dev_priv = obj->base.dev->dev_private; | 2839 | struct drm_i915_private *dev_priv = obj->base.dev->dev_private; |
2821 | struct write_fence args = { | 2840 | int reg = fence_number(dev_priv, fence); |
2822 | .dev = obj->base.dev, | 2841 | |
2823 | .fence = fence_number(dev_priv, fence), | 2842 | i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL); |
2824 | .obj = enable ? obj : NULL, | ||
2825 | }; | ||
2826 | |||
2827 | /* In order to fully serialize access to the fenced region and | ||
2828 | * the update to the fence register we need to take extreme | ||
2829 | * measures on SNB+. In theory, the write to the fence register | ||
2830 | * flushes all memory transactions before, and coupled with the | ||
2831 | * mb() placed around the register write we serialise all memory | ||
2832 | * operations with respect to the changes in the tiler. Yet, on | ||
2833 | * SNB+ we need to take a step further and emit an explicit wbinvd() | ||
2834 | * on each processor in order to manually flush all memory | ||
2835 | * transactions before updating the fence register. | ||
2836 | * | ||
2837 | * However, Valleyview complicates matter. There the wbinvd is | ||
2838 | * insufficient and unlike SNB/IVB requires the serialising | ||
2839 | * register write. (Note that that register write by itself is | ||
2840 | * conversely not sufficient for SNB+.) To compromise, we do both. | ||
2841 | */ | ||
2842 | if (INTEL_INFO(args.dev)->gen >= 6) | ||
2843 | on_each_cpu(i915_gem_write_fence__ipi, &args, 1); | ||
2844 | else | ||
2845 | i915_gem_write_fence(args.dev, args.fence, args.obj); | ||
2846 | 2843 | ||
2847 | if (enable) { | 2844 | if (enable) { |
2848 | obj->fence_reg = args.fence; | 2845 | obj->fence_reg = reg; |
2849 | fence->obj = obj; | 2846 | fence->obj = obj; |
2850 | list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list); | 2847 | list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list); |
2851 | } else { | 2848 | } else { |
@@ -2853,6 +2850,7 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj, | |||
2853 | fence->obj = NULL; | 2850 | fence->obj = NULL; |
2854 | list_del_init(&fence->lru_list); | 2851 | list_del_init(&fence->lru_list); |
2855 | } | 2852 | } |
2853 | obj->fence_dirty = false; | ||
2856 | } | 2854 | } |
2857 | 2855 | ||
2858 | static int | 2856 | static int |
@@ -2982,7 +2980,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj) | |||
2982 | return 0; | 2980 | return 0; |
2983 | 2981 | ||
2984 | i915_gem_object_update_fence(obj, reg, enable); | 2982 | i915_gem_object_update_fence(obj, reg, enable); |
2985 | obj->fence_dirty = false; | ||
2986 | 2983 | ||
2987 | return 0; | 2984 | return 0; |
2988 | } | 2985 | } |
@@ -4611,7 +4608,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) | |||
4611 | list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) | 4608 | list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) |
4612 | if (obj->pages_pin_count == 0) | 4609 | if (obj->pages_pin_count == 0) |
4613 | cnt += obj->base.size >> PAGE_SHIFT; | 4610 | cnt += obj->base.size >> PAGE_SHIFT; |
4614 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, global_list) | 4611 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) |
4615 | if (obj->pin_count == 0 && obj->pages_pin_count == 0) | 4612 | if (obj->pin_count == 0 && obj->pages_pin_count == 0) |
4616 | cnt += obj->base.size >> PAGE_SHIFT; | 4613 | cnt += obj->base.size >> PAGE_SHIFT; |
4617 | 4614 | ||