diff options
author | Dave Airlie <airlied@redhat.com> | 2014-11-03 16:36:06 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-11-03 16:36:06 -0500 |
commit | 041df3573d0ce74b7f2f505c4224c8ee9be14a7c (patch) | |
tree | bd70ff8a5613cd1f4bd0e316874aa90d00a0c5ff /drivers/gpu/drm/i915/intel_ringbuffer.c | |
parent | bbf0ef0334f2267687a92ec6d8114fd67b8157a3 (diff) | |
parent | 3eebaec630c2413a5e67bb7f49f0c6a53069a399 (diff) |
Merge tag 'drm-intel-next-2014-10-24' of git://anongit.freedesktop.org/drm-intel into drm-next
- suspend/resume/freeze/thaw unification from Imre
- wa list improvements from Mika&Arun
- display pll precomputation from Ander Conselvan, this removed the last
->mode_set callbacks, a big step towards implementing atomic modesets
- more kerneldoc for the interrupt code
- 180 rotation for cursors (Ville&Sonika)
- ULT/ULX feature check macros cleaned up thanks to Damien
- piles and piles of fixes all over, bug team seems to work!
* tag 'drm-intel-next-2014-10-24' of git://anongit.freedesktop.org/drm-intel: (61 commits)
drm/i915: Update DRIVER_DATE to 20141024
drm/i915: add comments on what stage a given PM handler is called
drm/i915: unify switcheroo and legacy suspend/resume handlers
drm/i915: add poweroff_late handler
drm/i915: sanitize suspend/resume helper function names
drm/i915: unify S3 and S4 suspend/resume handlers
drm/i915: disable/re-enable PCI device around S4 freeze/thaw
drm/i915: enable output polling during S4 thaw
drm/i915: check for GT faults in all resume handlers and driver load time
drm/i915: remove unused restore_gtt_mappings optimization during suspend
drm/i915: fix S4 suspend while switcheroo state is off
drm/i915: vlv: fix switcheroo/legacy suspend/resume
drm/i915: propagate error from legacy resume handler
drm/i915: unify legacy S3 suspend and S4 freeze handlers
drm/i915: factor out i915_drm_suspend_late
drm/i915: Emit even number of dwords when emitting LRIs
drm/i915: Add rotation support for cursor plane (v5)
drm/i915: Correctly reject invalid flags for wait_ioctl
drm/i915: use macros to assign mmio access functions
drm/i915: only run hsw_power_well_post_enable when really needed
...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 190 |
1 files changed, 107 insertions, 83 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 816a6926df28..a8f72e8d64e3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -665,80 +665,108 @@ err: | |||
665 | return ret; | 665 | return ret; |
666 | } | 666 | } |
667 | 667 | ||
668 | static inline void intel_ring_emit_wa(struct intel_engine_cs *ring, | 668 | static int intel_ring_workarounds_emit(struct intel_engine_cs *ring) |
669 | u32 addr, u32 value) | ||
670 | { | 669 | { |
670 | int ret, i; | ||
671 | struct drm_device *dev = ring->dev; | 671 | struct drm_device *dev = ring->dev; |
672 | struct drm_i915_private *dev_priv = dev->dev_private; | 672 | struct drm_i915_private *dev_priv = dev->dev_private; |
673 | struct i915_workarounds *w = &dev_priv->workarounds; | ||
673 | 674 | ||
674 | if (WARN_ON(dev_priv->num_wa_regs >= I915_MAX_WA_REGS)) | 675 | if (WARN_ON(w->count == 0)) |
675 | return; | 676 | return 0; |
676 | 677 | ||
677 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); | 678 | ring->gpu_caches_dirty = true; |
678 | intel_ring_emit(ring, addr); | 679 | ret = intel_ring_flush_all_caches(ring); |
679 | intel_ring_emit(ring, value); | 680 | if (ret) |
681 | return ret; | ||
680 | 682 | ||
681 | dev_priv->intel_wa_regs[dev_priv->num_wa_regs].addr = addr; | 683 | ret = intel_ring_begin(ring, (w->count * 2 + 2)); |
682 | dev_priv->intel_wa_regs[dev_priv->num_wa_regs].mask = value & 0xFFFF; | 684 | if (ret) |
683 | /* value is updated with the status of remaining bits of this | 685 | return ret; |
684 | * register when it is read from debugfs file | 686 | |
685 | */ | 687 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); |
686 | dev_priv->intel_wa_regs[dev_priv->num_wa_regs].value = value; | 688 | for (i = 0; i < w->count; i++) { |
687 | dev_priv->num_wa_regs++; | 689 | intel_ring_emit(ring, w->reg[i].addr); |
690 | intel_ring_emit(ring, w->reg[i].value); | ||
691 | } | ||
692 | intel_ring_emit(ring, MI_NOOP); | ||
693 | |||
694 | intel_ring_advance(ring); | ||
695 | |||
696 | ring->gpu_caches_dirty = true; | ||
697 | ret = intel_ring_flush_all_caches(ring); | ||
698 | if (ret) | ||
699 | return ret; | ||
688 | 700 | ||
689 | return; | 701 | DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); |
702 | |||
703 | return 0; | ||
690 | } | 704 | } |
691 | 705 | ||
706 | static int wa_add(struct drm_i915_private *dev_priv, | ||
707 | const u32 addr, const u32 val, const u32 mask) | ||
708 | { | ||
709 | const u32 idx = dev_priv->workarounds.count; | ||
710 | |||
711 | if (WARN_ON(idx >= I915_MAX_WA_REGS)) | ||
712 | return -ENOSPC; | ||
713 | |||
714 | dev_priv->workarounds.reg[idx].addr = addr; | ||
715 | dev_priv->workarounds.reg[idx].value = val; | ||
716 | dev_priv->workarounds.reg[idx].mask = mask; | ||
717 | |||
718 | dev_priv->workarounds.count++; | ||
719 | |||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | #define WA_REG(addr, val, mask) { \ | ||
724 | const int r = wa_add(dev_priv, (addr), (val), (mask)); \ | ||
725 | if (r) \ | ||
726 | return r; \ | ||
727 | } | ||
728 | |||
729 | #define WA_SET_BIT_MASKED(addr, mask) \ | ||
730 | WA_REG(addr, _MASKED_BIT_ENABLE(mask), (mask) & 0xffff) | ||
731 | |||
732 | #define WA_CLR_BIT_MASKED(addr, mask) \ | ||
733 | WA_REG(addr, _MASKED_BIT_DISABLE(mask), (mask) & 0xffff) | ||
734 | |||
735 | #define WA_SET_BIT(addr, mask) WA_REG(addr, I915_READ(addr) | (mask), mask) | ||
736 | #define WA_CLR_BIT(addr, mask) WA_REG(addr, I915_READ(addr) & ~(mask), mask) | ||
737 | |||
738 | #define WA_WRITE(addr, val) WA_REG(addr, val, 0xffffffff) | ||
739 | |||
692 | static int bdw_init_workarounds(struct intel_engine_cs *ring) | 740 | static int bdw_init_workarounds(struct intel_engine_cs *ring) |
693 | { | 741 | { |
694 | int ret; | ||
695 | struct drm_device *dev = ring->dev; | 742 | struct drm_device *dev = ring->dev; |
696 | struct drm_i915_private *dev_priv = dev->dev_private; | 743 | struct drm_i915_private *dev_priv = dev->dev_private; |
697 | 744 | ||
698 | /* | ||
699 | * workarounds applied in this fn are part of register state context, | ||
700 | * they need to be re-initialized followed by gpu reset, suspend/resume, | ||
701 | * module reload. | ||
702 | */ | ||
703 | dev_priv->num_wa_regs = 0; | ||
704 | memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs)); | ||
705 | |||
706 | /* | ||
707 | * update the number of dwords required based on the | ||
708 | * actual number of workarounds applied | ||
709 | */ | ||
710 | ret = intel_ring_begin(ring, 18); | ||
711 | if (ret) | ||
712 | return ret; | ||
713 | |||
714 | /* WaDisablePartialInstShootdown:bdw */ | 745 | /* WaDisablePartialInstShootdown:bdw */ |
715 | /* WaDisableThreadStallDopClockGating:bdw */ | 746 | /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ |
716 | /* FIXME: Unclear whether we really need this on production bdw. */ | 747 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, |
717 | intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, | 748 | PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | |
718 | _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | 749 | STALL_DOP_GATING_DISABLE); |
719 | | STALL_DOP_GATING_DISABLE)); | ||
720 | 750 | ||
721 | /* WaDisableDopClockGating:bdw May not be needed for production */ | 751 | /* WaDisableDopClockGating:bdw */ |
722 | intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2, | 752 | WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, |
723 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); | 753 | DOP_CLOCK_GATING_DISABLE); |
724 | 754 | ||
725 | intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3, | 755 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, |
726 | _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); | 756 | GEN8_SAMPLER_POWER_BYPASS_DIS); |
727 | 757 | ||
728 | /* Use Force Non-Coherent whenever executing a 3D context. This is a | 758 | /* Use Force Non-Coherent whenever executing a 3D context. This is a |
729 | * workaround for for a possible hang in the unlikely event a TLB | 759 | * workaround for for a possible hang in the unlikely event a TLB |
730 | * invalidation occurs during a PSD flush. | 760 | * invalidation occurs during a PSD flush. |
731 | */ | 761 | */ |
732 | /* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */ | 762 | /* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */ |
733 | intel_ring_emit_wa(ring, HDC_CHICKEN0, | 763 | WA_SET_BIT_MASKED(HDC_CHICKEN0, |
734 | _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT | | 764 | HDC_FORCE_NON_COHERENT | |
735 | (IS_BDW_GT3(dev) ? | 765 | (IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); |
736 | HDC_FENCE_DEST_SLM_DISABLE : 0) | ||
737 | )); | ||
738 | 766 | ||
739 | /* Wa4x4STCOptimizationDisable:bdw */ | 767 | /* Wa4x4STCOptimizationDisable:bdw */ |
740 | intel_ring_emit_wa(ring, CACHE_MODE_1, | 768 | WA_SET_BIT_MASKED(CACHE_MODE_1, |
741 | _MASKED_BIT_ENABLE(GEN8_4x4_STC_OPTIMIZATION_DISABLE)); | 769 | GEN8_4x4_STC_OPTIMIZATION_DISABLE); |
742 | 770 | ||
743 | /* | 771 | /* |
744 | * BSpec recommends 8x4 when MSAA is used, | 772 | * BSpec recommends 8x4 when MSAA is used, |
@@ -748,52 +776,50 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring) | |||
748 | * disable bit, which we don't touch here, but it's good | 776 | * disable bit, which we don't touch here, but it's good |
749 | * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). | 777 | * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). |
750 | */ | 778 | */ |
751 | intel_ring_emit_wa(ring, GEN7_GT_MODE, | 779 | WA_SET_BIT_MASKED(GEN7_GT_MODE, |
752 | GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4); | 780 | GEN6_WIZ_HASHING_MASK | GEN6_WIZ_HASHING_16x4); |
753 | |||
754 | intel_ring_advance(ring); | ||
755 | |||
756 | DRM_DEBUG_DRIVER("Number of Workarounds applied: %d\n", | ||
757 | dev_priv->num_wa_regs); | ||
758 | 781 | ||
759 | return 0; | 782 | return 0; |
760 | } | 783 | } |
761 | 784 | ||
762 | static int chv_init_workarounds(struct intel_engine_cs *ring) | 785 | static int chv_init_workarounds(struct intel_engine_cs *ring) |
763 | { | 786 | { |
764 | int ret; | ||
765 | struct drm_device *dev = ring->dev; | 787 | struct drm_device *dev = ring->dev; |
766 | struct drm_i915_private *dev_priv = dev->dev_private; | 788 | struct drm_i915_private *dev_priv = dev->dev_private; |
767 | 789 | ||
768 | /* | ||
769 | * workarounds applied in this fn are part of register state context, | ||
770 | * they need to be re-initialized followed by gpu reset, suspend/resume, | ||
771 | * module reload. | ||
772 | */ | ||
773 | dev_priv->num_wa_regs = 0; | ||
774 | memset(dev_priv->intel_wa_regs, 0, sizeof(dev_priv->intel_wa_regs)); | ||
775 | |||
776 | ret = intel_ring_begin(ring, 12); | ||
777 | if (ret) | ||
778 | return ret; | ||
779 | |||
780 | /* WaDisablePartialInstShootdown:chv */ | 790 | /* WaDisablePartialInstShootdown:chv */ |
781 | intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, | 791 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, |
782 | _MASKED_BIT_ENABLE(PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE)); | 792 | PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); |
783 | 793 | ||
784 | /* WaDisableThreadStallDopClockGating:chv */ | 794 | /* WaDisableThreadStallDopClockGating:chv */ |
785 | intel_ring_emit_wa(ring, GEN8_ROW_CHICKEN, | 795 | WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, |
786 | _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE)); | 796 | STALL_DOP_GATING_DISABLE); |
787 | 797 | ||
788 | /* WaDisableDopClockGating:chv (pre-production hw) */ | 798 | /* WaDisableDopClockGating:chv (pre-production hw) */ |
789 | intel_ring_emit_wa(ring, GEN7_ROW_CHICKEN2, | 799 | WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, |
790 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); | 800 | DOP_CLOCK_GATING_DISABLE); |
791 | 801 | ||
792 | /* WaDisableSamplerPowerBypass:chv (pre-production hw) */ | 802 | /* WaDisableSamplerPowerBypass:chv (pre-production hw) */ |
793 | intel_ring_emit_wa(ring, HALF_SLICE_CHICKEN3, | 803 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, |
794 | _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); | 804 | GEN8_SAMPLER_POWER_BYPASS_DIS); |
795 | 805 | ||
796 | intel_ring_advance(ring); | 806 | return 0; |
807 | } | ||
808 | |||
809 | static int init_workarounds_ring(struct intel_engine_cs *ring) | ||
810 | { | ||
811 | struct drm_device *dev = ring->dev; | ||
812 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
813 | |||
814 | WARN_ON(ring->id != RCS); | ||
815 | |||
816 | dev_priv->workarounds.count = 0; | ||
817 | |||
818 | if (IS_BROADWELL(dev)) | ||
819 | return bdw_init_workarounds(ring); | ||
820 | |||
821 | if (IS_CHERRYVIEW(dev)) | ||
822 | return chv_init_workarounds(ring); | ||
797 | 823 | ||
798 | return 0; | 824 | return 0; |
799 | } | 825 | } |
@@ -853,7 +879,7 @@ static int init_render_ring(struct intel_engine_cs *ring) | |||
853 | if (HAS_L3_DPF(dev)) | 879 | if (HAS_L3_DPF(dev)) |
854 | I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); | 880 | I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); |
855 | 881 | ||
856 | return ret; | 882 | return init_workarounds_ring(ring); |
857 | } | 883 | } |
858 | 884 | ||
859 | static void render_ring_cleanup(struct intel_engine_cs *ring) | 885 | static void render_ring_cleanup(struct intel_engine_cs *ring) |
@@ -2299,10 +2325,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev) | |||
2299 | dev_priv->semaphore_obj = obj; | 2325 | dev_priv->semaphore_obj = obj; |
2300 | } | 2326 | } |
2301 | } | 2327 | } |
2302 | if (IS_CHERRYVIEW(dev)) | 2328 | |
2303 | ring->init_context = chv_init_workarounds; | 2329 | ring->init_context = intel_ring_workarounds_emit; |
2304 | else | ||
2305 | ring->init_context = bdw_init_workarounds; | ||
2306 | ring->add_request = gen6_add_request; | 2330 | ring->add_request = gen6_add_request; |
2307 | ring->flush = gen8_render_ring_flush; | 2331 | ring->flush = gen8_render_ring_flush; |
2308 | ring->irq_get = gen8_ring_get_irq; | 2332 | ring->irq_get = gen8_ring_get_irq; |