aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-11-03 16:36:06 -0500
committerDave Airlie <airlied@redhat.com>2014-11-03 16:36:06 -0500
commit041df3573d0ce74b7f2f505c4224c8ee9be14a7c (patch)
treebd70ff8a5613cd1f4bd0e316874aa90d00a0c5ff /drivers/gpu/drm/i915/intel_ringbuffer.c
parentbbf0ef0334f2267687a92ec6d8114fd67b8157a3 (diff)
parent3eebaec630c2413a5e67bb7f49f0c6a53069a399 (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.c190
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
668static inline void intel_ring_emit_wa(struct intel_engine_cs *ring, 668static 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
706static 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
692static int bdw_init_workarounds(struct intel_engine_cs *ring) 740static 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
762static int chv_init_workarounds(struct intel_engine_cs *ring) 785static 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
809static 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
859static void render_ring_cleanup(struct intel_engine_cs *ring) 885static 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;