aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c1
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c4
-rw-r--r--drivers/gpu/drm/i915/intel_workarounds.c492
-rw-r--r--drivers/gpu/drm/i915/intel_workarounds.h23
5 files changed, 354 insertions, 168 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c2a3ba7e09e0..6f497cf31ffc 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1467,6 +1467,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
1467 1467
1468 intel_uncore_sanitize(dev_priv); 1468 intel_uncore_sanitize(dev_priv);
1469 1469
1470 intel_gt_init_workarounds(dev_priv);
1470 i915_gem_load_init_fences(dev_priv); 1471 i915_gem_load_init_fences(dev_priv);
1471 1472
1472 /* On the 945G/GM, the chipset reports the MSI capability on the 1473 /* On the 945G/GM, the chipset reports the MSI capability on the
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 12b8476b09a2..d725390d5a48 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -69,6 +69,7 @@
69#include "intel_ringbuffer.h" 69#include "intel_ringbuffer.h"
70#include "intel_uncore.h" 70#include "intel_uncore.h"
71#include "intel_wopcm.h" 71#include "intel_wopcm.h"
72#include "intel_workarounds.h"
72#include "intel_uc.h" 73#include "intel_uc.h"
73 74
74#include "i915_gem.h" 75#include "i915_gem.h"
@@ -1653,6 +1654,7 @@ struct drm_i915_private {
1653 int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; 1654 int dpio_phy_iosf_port[I915_NUM_PHYS_VLV];
1654 1655
1655 struct i915_workarounds workarounds; 1656 struct i915_workarounds workarounds;
1657 struct i915_wa_list gt_wa_list;
1656 1658
1657 struct i915_frontbuffer_tracking fb_tracking; 1659 struct i915_frontbuffer_tracking fb_tracking;
1658 1660
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 834240a9b262..ad5a115e47b6 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5300,7 +5300,7 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
5300 I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ? 5300 I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ?
5301 LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); 5301 LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
5302 5302
5303 intel_gt_workarounds_apply(dev_priv); 5303 intel_gt_apply_workarounds(dev_priv);
5304 5304
5305 i915_gem_init_swizzling(dev_priv); 5305 i915_gem_init_swizzling(dev_priv);
5306 5306
@@ -5672,6 +5672,8 @@ void i915_gem_fini(struct drm_i915_private *dev_priv)
5672 i915_gem_contexts_fini(dev_priv); 5672 i915_gem_contexts_fini(dev_priv);
5673 mutex_unlock(&dev_priv->drm.struct_mutex); 5673 mutex_unlock(&dev_priv->drm.struct_mutex);
5674 5674
5675 intel_wa_list_free(&dev_priv->gt_wa_list);
5676
5675 intel_cleanup_gt_powersave(dev_priv); 5677 intel_cleanup_gt_powersave(dev_priv);
5676 5678
5677 intel_uc_fini_misc(dev_priv); 5679 intel_uc_fini_misc(dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c
index e5cd6c6c66c3..c3256ab2c411 100644
--- a/drivers/gpu/drm/i915/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/intel_workarounds.c
@@ -48,6 +48,20 @@
48 * - Public functions to init or apply the given workaround type. 48 * - Public functions to init or apply the given workaround type.
49 */ 49 */
50 50
51static void wa_init_start(struct i915_wa_list *wal, const char *name)
52{
53 wal->name = name;
54}
55
56static void wa_init_finish(struct i915_wa_list *wal)
57{
58 if (!wal->count)
59 return;
60
61 DRM_DEBUG_DRIVER("Initialized %u %s workarounds\n",
62 wal->count, wal->name);
63}
64
51static void wa_add(struct drm_i915_private *i915, 65static void wa_add(struct drm_i915_private *i915,
52 i915_reg_t reg, const u32 mask, const u32 val) 66 i915_reg_t reg, const u32 mask, const u32 val)
53{ 67{
@@ -575,160 +589,239 @@ int intel_ctx_workarounds_emit(struct i915_request *rq)
575 return 0; 589 return 0;
576} 590}
577 591
578static void bdw_gt_workarounds_apply(struct drm_i915_private *dev_priv) 592static void
593wal_add(struct i915_wa_list *wal, const struct i915_wa *wa)
594{
595 const unsigned int grow = 1 << 4;
596
597 GEM_BUG_ON(!is_power_of_2(grow));
598
599 if (IS_ALIGNED(wal->count, grow)) { /* Either uninitialized or full. */
600 struct i915_wa *list;
601
602 list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa),
603 GFP_KERNEL);
604 if (!list) {
605 DRM_ERROR("No space for workaround init!\n");
606 return;
607 }
608
609 if (wal->list)
610 memcpy(list, wal->list, sizeof(*wa) * wal->count);
611
612 wal->list = list;
613 }
614
615 wal->list[wal->count++] = *wa;
616}
617
618static void
619wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
620{
621 struct i915_wa wa = {
622 .reg = reg,
623 .mask = val,
624 .val = _MASKED_BIT_ENABLE(val)
625 };
626
627 wal_add(wal, &wa);
628}
629
630static void
631wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask,
632 u32 val)
579{ 633{
634 struct i915_wa wa = {
635 .reg = reg,
636 .mask = mask,
637 .val = val
638 };
639
640 wal_add(wal, &wa);
641}
642
643static void
644wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
645{
646 wa_write_masked_or(wal, reg, ~0, val);
580} 647}
581 648
582static void chv_gt_workarounds_apply(struct drm_i915_private *dev_priv) 649static void
650wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
583{ 651{
652 wa_write_masked_or(wal, reg, val, val);
584} 653}
585 654
586static void gen9_gt_workarounds_apply(struct drm_i915_private *dev_priv) 655static void gen9_gt_workarounds_init(struct drm_i915_private *i915)
587{ 656{
657 struct i915_wa_list *wal = &i915->gt_wa_list;
658
588 /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */ 659 /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */
589 I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, 660 wa_masked_en(wal,
590 _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); 661 GEN9_CSFE_CHICKEN1_RCS,
662 GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE);
663
591 664
592 /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */ 665 /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */
593 I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 666 wa_write_or(wal,
594 GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 667 BDW_SCRATCH1,
668 GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
595 669
596 /* WaDisableKillLogic:bxt,skl,kbl */ 670 /* WaDisableKillLogic:bxt,skl,kbl */
597 if (!IS_COFFEELAKE(dev_priv)) 671 if (!IS_COFFEELAKE(i915))
598 I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 672 wa_write_or(wal,
599 ECOCHK_DIS_TLB); 673 GAM_ECOCHK,
674 ECOCHK_DIS_TLB);
600 675
601 if (HAS_LLC(dev_priv)) { 676 if (HAS_LLC(i915)) {
602 /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl 677 /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl
603 * 678 *
604 * Must match Display Engine. See 679 * Must match Display Engine. See
605 * WaCompressedResourceDisplayNewHashMode. 680 * WaCompressedResourceDisplayNewHashMode.
606 */ 681 */
607 I915_WRITE(MMCD_MISC_CTRL, 682 wa_write_or(wal,
608 I915_READ(MMCD_MISC_CTRL) | 683 MMCD_MISC_CTRL,
609 MMCD_PCLA | 684 MMCD_PCLA | MMCD_HOTSPOT_EN);
610 MMCD_HOTSPOT_EN);
611 } 685 }
612 686
613 /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */ 687 /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */
614 I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 688 wa_write_or(wal,
615 BDW_DISABLE_HDC_INVALIDATION); 689 GAM_ECOCHK,
690 BDW_DISABLE_HDC_INVALIDATION);
616 691
617 /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */ 692 /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */
618 if (IS_GEN9_LP(dev_priv)) { 693 if (IS_GEN9_LP(i915))
619 u32 val = I915_READ(GEN8_L3SQCREG1); 694 wa_write_masked_or(wal,
620 695 GEN8_L3SQCREG1,
621 val &= ~L3_PRIO_CREDITS_MASK; 696 L3_PRIO_CREDITS_MASK,
622 val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); 697 L3_GENERAL_PRIO_CREDITS(62) |
623 I915_WRITE(GEN8_L3SQCREG1, val); 698 L3_HIGH_PRIO_CREDITS(2));
624 }
625 699
626 /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */ 700 /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */
627 I915_WRITE(GEN8_L3SQCREG4, 701 wa_write_or(wal,
628 I915_READ(GEN8_L3SQCREG4) | GEN8_LQSC_FLUSH_COHERENT_LINES); 702 GEN8_L3SQCREG4,
703 GEN8_LQSC_FLUSH_COHERENT_LINES);
629 704
630 /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ 705 /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */
631 I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 706 wa_masked_en(wal,
632 _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 707 GEN7_FF_SLICE_CS_CHICKEN1,
708 GEN9_FFSC_PERCTX_PREEMPT_CTRL);
633} 709}
634 710
635static void skl_gt_workarounds_apply(struct drm_i915_private *dev_priv) 711static void skl_gt_workarounds_init(struct drm_i915_private *i915)
636{ 712{
637 gen9_gt_workarounds_apply(dev_priv); 713 struct i915_wa_list *wal = &i915->gt_wa_list;
714
715 gen9_gt_workarounds_init(i915);
638 716
639 /* WaEnableGapsTsvCreditFix:skl */ 717 /* WaEnableGapsTsvCreditFix:skl */
640 I915_WRITE(GEN8_GARBCNTL, 718 wa_write_or(wal,
641 I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); 719 GEN8_GARBCNTL,
720 GEN9_GAPS_TSV_CREDIT_DISABLE);
642 721
643 /* WaDisableGafsUnitClkGating:skl */ 722 /* WaDisableGafsUnitClkGating:skl */
644 I915_WRITE(GEN7_UCGCTL4, 723 wa_write_or(wal,
645 I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 724 GEN7_UCGCTL4,
725 GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
646 726
647 /* WaInPlaceDecompressionHang:skl */ 727 /* WaInPlaceDecompressionHang:skl */
648 if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) 728 if (IS_SKL_REVID(i915, SKL_REVID_H0, REVID_FOREVER))
649 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, 729 wa_write_or(wal,
650 I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | 730 GEN9_GAMT_ECO_REG_RW_IA,
651 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 731 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
652} 732}
653 733
654static void bxt_gt_workarounds_apply(struct drm_i915_private *dev_priv) 734static void bxt_gt_workarounds_init(struct drm_i915_private *i915)
655{ 735{
656 gen9_gt_workarounds_apply(dev_priv); 736 struct i915_wa_list *wal = &i915->gt_wa_list;
737
738 gen9_gt_workarounds_init(i915);
657 739
658 /* WaDisablePooledEuLoadBalancingFix:bxt */ 740 /* WaDisablePooledEuLoadBalancingFix:bxt */
659 I915_WRITE(FF_SLICE_CS_CHICKEN2, 741 wa_masked_en(wal,
660 _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); 742 FF_SLICE_CS_CHICKEN2,
743 GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE);
661 744
662 /* WaInPlaceDecompressionHang:bxt */ 745 /* WaInPlaceDecompressionHang:bxt */
663 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, 746 wa_write_or(wal,
664 I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | 747 GEN9_GAMT_ECO_REG_RW_IA,
665 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 748 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
666} 749}
667 750
668static void kbl_gt_workarounds_apply(struct drm_i915_private *dev_priv) 751static void kbl_gt_workarounds_init(struct drm_i915_private *i915)
669{ 752{
670 gen9_gt_workarounds_apply(dev_priv); 753 struct i915_wa_list *wal = &i915->gt_wa_list;
754
755 gen9_gt_workarounds_init(i915);
671 756
672 /* WaEnableGapsTsvCreditFix:kbl */ 757 /* WaEnableGapsTsvCreditFix:kbl */
673 I915_WRITE(GEN8_GARBCNTL, 758 wa_write_or(wal,
674 I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); 759 GEN8_GARBCNTL,
760 GEN9_GAPS_TSV_CREDIT_DISABLE);
675 761
676 /* WaDisableDynamicCreditSharing:kbl */ 762 /* WaDisableDynamicCreditSharing:kbl */
677 if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 763 if (IS_KBL_REVID(i915, 0, KBL_REVID_B0))
678 I915_WRITE(GAMT_CHKN_BIT_REG, 764 wa_write_or(wal,
679 I915_READ(GAMT_CHKN_BIT_REG) | 765 GAMT_CHKN_BIT_REG,
680 GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 766 GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
681 767
682 /* WaDisableGafsUnitClkGating:kbl */ 768 /* WaDisableGafsUnitClkGating:kbl */
683 I915_WRITE(GEN7_UCGCTL4, 769 wa_write_or(wal,
684 I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 770 GEN7_UCGCTL4,
771 GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
685 772
686 /* WaInPlaceDecompressionHang:kbl */ 773 /* WaInPlaceDecompressionHang:kbl */
687 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, 774 wa_write_or(wal,
688 I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | 775 GEN9_GAMT_ECO_REG_RW_IA,
689 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 776 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
690 777
691 /* WaKBLVECSSemaphoreWaitPoll:kbl */ 778 /* WaKBLVECSSemaphoreWaitPoll:kbl */
692 if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_E0)) { 779 if (IS_KBL_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) {
693 struct intel_engine_cs *engine; 780 struct intel_engine_cs *engine;
694 unsigned int tmp; 781 unsigned int tmp;
695 782
696 for_each_engine(engine, dev_priv, tmp) { 783 for_each_engine(engine, i915, tmp) {
697 if (engine->id == RCS) 784 if (engine->id == RCS)
698 continue; 785 continue;
699 786
700 I915_WRITE(RING_SEMA_WAIT_POLL(engine->mmio_base), 1); 787 wa_write(wal,
788 RING_SEMA_WAIT_POLL(engine->mmio_base),
789 1);
701 } 790 }
702 } 791 }
703} 792}
704 793
705static void glk_gt_workarounds_apply(struct drm_i915_private *dev_priv) 794static void glk_gt_workarounds_init(struct drm_i915_private *i915)
706{ 795{
707 gen9_gt_workarounds_apply(dev_priv); 796 gen9_gt_workarounds_init(i915);
708} 797}
709 798
710static void cfl_gt_workarounds_apply(struct drm_i915_private *dev_priv) 799static void cfl_gt_workarounds_init(struct drm_i915_private *i915)
711{ 800{
712 gen9_gt_workarounds_apply(dev_priv); 801 struct i915_wa_list *wal = &i915->gt_wa_list;
802
803 gen9_gt_workarounds_init(i915);
713 804
714 /* WaEnableGapsTsvCreditFix:cfl */ 805 /* WaEnableGapsTsvCreditFix:cfl */
715 I915_WRITE(GEN8_GARBCNTL, 806 wa_write_or(wal,
716 I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); 807 GEN8_GARBCNTL,
808 GEN9_GAPS_TSV_CREDIT_DISABLE);
717 809
718 /* WaDisableGafsUnitClkGating:cfl */ 810 /* WaDisableGafsUnitClkGating:cfl */
719 I915_WRITE(GEN7_UCGCTL4, 811 wa_write_or(wal,
720 I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 812 GEN7_UCGCTL4,
813 GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
721 814
722 /* WaInPlaceDecompressionHang:cfl */ 815 /* WaInPlaceDecompressionHang:cfl */
723 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, 816 wa_write_or(wal,
724 I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | 817 GEN9_GAMT_ECO_REG_RW_IA,
725 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 818 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
726} 819}
727 820
728static void wa_init_mcr(struct drm_i915_private *dev_priv) 821static void wa_init_mcr(struct drm_i915_private *dev_priv)
729{ 822{
730 const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu); 823 const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu);
731 u32 mcr; 824 struct i915_wa_list *wal = &dev_priv->gt_wa_list;
732 u32 mcr_slice_subslice_mask; 825 u32 mcr_slice_subslice_mask;
733 826
734 /* 827 /*
@@ -765,8 +858,6 @@ static void wa_init_mcr(struct drm_i915_private *dev_priv)
765 WARN_ON((enabled_mask & disabled_mask) != enabled_mask); 858 WARN_ON((enabled_mask & disabled_mask) != enabled_mask);
766 } 859 }
767 860
768 mcr = I915_READ(GEN8_MCR_SELECTOR);
769
770 if (INTEL_GEN(dev_priv) >= 11) 861 if (INTEL_GEN(dev_priv) >= 11)
771 mcr_slice_subslice_mask = GEN11_MCR_SLICE_MASK | 862 mcr_slice_subslice_mask = GEN11_MCR_SLICE_MASK |
772 GEN11_MCR_SUBSLICE_MASK; 863 GEN11_MCR_SUBSLICE_MASK;
@@ -784,156 +875,225 @@ static void wa_init_mcr(struct drm_i915_private *dev_priv)
784 * occasions, such as INSTDONE, where this value is dependent 875 * occasions, such as INSTDONE, where this value is dependent
785 * on s/ss combo, the read should be done with read_subslice_reg. 876 * on s/ss combo, the read should be done with read_subslice_reg.
786 */ 877 */
787 mcr &= ~mcr_slice_subslice_mask; 878 wa_write_masked_or(wal,
788 mcr |= intel_calculate_mcr_s_ss_select(dev_priv); 879 GEN8_MCR_SELECTOR,
789 I915_WRITE(GEN8_MCR_SELECTOR, mcr); 880 mcr_slice_subslice_mask,
881 intel_calculate_mcr_s_ss_select(dev_priv));
790} 882}
791 883
792static void cnl_gt_workarounds_apply(struct drm_i915_private *dev_priv) 884static void cnl_gt_workarounds_init(struct drm_i915_private *i915)
793{ 885{
794 wa_init_mcr(dev_priv); 886 struct i915_wa_list *wal = &i915->gt_wa_list;
887
888 wa_init_mcr(i915);
795 889
796 /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ 890 /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */
797 if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) 891 if (IS_CNL_REVID(i915, CNL_REVID_B0, CNL_REVID_B0))
798 I915_WRITE(GAMT_CHKN_BIT_REG, 892 wa_write_or(wal,
799 I915_READ(GAMT_CHKN_BIT_REG) | 893 GAMT_CHKN_BIT_REG,
800 GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); 894 GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT);
801 895
802 /* WaInPlaceDecompressionHang:cnl */ 896 /* WaInPlaceDecompressionHang:cnl */
803 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, 897 wa_write_or(wal,
804 I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | 898 GEN9_GAMT_ECO_REG_RW_IA,
805 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 899 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
806 900
807 /* WaEnablePreemptionGranularityControlByUMD:cnl */ 901 /* WaEnablePreemptionGranularityControlByUMD:cnl */
808 I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 902 wa_masked_en(wal,
809 _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 903 GEN7_FF_SLICE_CS_CHICKEN1,
904 GEN9_FFSC_PERCTX_PREEMPT_CTRL);
810} 905}
811 906
812static void icl_gt_workarounds_apply(struct drm_i915_private *dev_priv) 907static void icl_gt_workarounds_init(struct drm_i915_private *i915)
813{ 908{
814 wa_init_mcr(dev_priv); 909 struct i915_wa_list *wal = &i915->gt_wa_list;
910
911 wa_init_mcr(i915);
815 912
816 /* This is not an Wa. Enable for better image quality */ 913 /* This is not an Wa. Enable for better image quality */
817 I915_WRITE(_3D_CHICKEN3, 914 wa_masked_en(wal,
818 _MASKED_BIT_ENABLE(_3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE)); 915 _3D_CHICKEN3,
916 _3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE);
819 917
820 /* WaInPlaceDecompressionHang:icl */ 918 /* WaInPlaceDecompressionHang:icl */
821 I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, 919 wa_write_or(wal,
822 I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | 920 GEN9_GAMT_ECO_REG_RW_IA,
823 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 921 GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS);
824 922
825 /* WaPipelineFlushCoherentLines:icl */ 923 /* WaPipelineFlushCoherentLines:icl */
826 I915_WRITE(GEN8_L3SQCREG4, 924 wa_write_or(wal,
827 I915_READ(GEN8_L3SQCREG4) | 925 GEN8_L3SQCREG4,
828 GEN8_LQSC_FLUSH_COHERENT_LINES); 926 GEN8_LQSC_FLUSH_COHERENT_LINES);
829 927
830 /* Wa_1405543622:icl 928 /* Wa_1405543622:icl
831 * Formerly known as WaGAPZPriorityScheme 929 * Formerly known as WaGAPZPriorityScheme
832 */ 930 */
833 I915_WRITE(GEN8_GARBCNTL, 931 wa_write_or(wal,
834 I915_READ(GEN8_GARBCNTL) | 932 GEN8_GARBCNTL,
835 GEN11_ARBITRATION_PRIO_ORDER_MASK); 933 GEN11_ARBITRATION_PRIO_ORDER_MASK);
836 934
837 /* Wa_1604223664:icl 935 /* Wa_1604223664:icl
838 * Formerly known as WaL3BankAddressHashing 936 * Formerly known as WaL3BankAddressHashing
839 */ 937 */
840 I915_WRITE(GEN8_GARBCNTL, 938 wa_write_masked_or(wal,
841 (I915_READ(GEN8_GARBCNTL) & ~GEN11_HASH_CTRL_EXCL_MASK) | 939 GEN8_GARBCNTL,
842 GEN11_HASH_CTRL_EXCL_BIT0); 940 GEN11_HASH_CTRL_EXCL_MASK,
843 I915_WRITE(GEN11_GLBLINVL, 941 GEN11_HASH_CTRL_EXCL_BIT0);
844 (I915_READ(GEN11_GLBLINVL) & ~GEN11_BANK_HASH_ADDR_EXCL_MASK) | 942 wa_write_masked_or(wal,
845 GEN11_BANK_HASH_ADDR_EXCL_BIT0); 943 GEN11_GLBLINVL,
944 GEN11_BANK_HASH_ADDR_EXCL_MASK,
945 GEN11_BANK_HASH_ADDR_EXCL_BIT0);
846 946
847 /* WaModifyGamTlbPartitioning:icl */ 947 /* WaModifyGamTlbPartitioning:icl */
848 I915_WRITE(GEN11_GACB_PERF_CTRL, 948 wa_write_masked_or(wal,
849 (I915_READ(GEN11_GACB_PERF_CTRL) & ~GEN11_HASH_CTRL_MASK) | 949 GEN11_GACB_PERF_CTRL,
850 GEN11_HASH_CTRL_BIT0 | GEN11_HASH_CTRL_BIT4); 950 GEN11_HASH_CTRL_MASK,
951 GEN11_HASH_CTRL_BIT0 | GEN11_HASH_CTRL_BIT4);
851 952
852 /* Wa_1405733216:icl 953 /* Wa_1405733216:icl
853 * Formerly known as WaDisableCleanEvicts 954 * Formerly known as WaDisableCleanEvicts
854 */ 955 */
855 I915_WRITE(GEN8_L3SQCREG4, 956 wa_write_or(wal,
856 I915_READ(GEN8_L3SQCREG4) | 957 GEN8_L3SQCREG4,
857 GEN11_LQSC_CLEAN_EVICT_DISABLE); 958 GEN11_LQSC_CLEAN_EVICT_DISABLE);
858 959
859 /* Wa_1405766107:icl 960 /* Wa_1405766107:icl
860 * Formerly known as WaCL2SFHalfMaxAlloc 961 * Formerly known as WaCL2SFHalfMaxAlloc
861 */ 962 */
862 I915_WRITE(GEN11_LSN_UNSLCVC, 963 wa_write_or(wal,
863 I915_READ(GEN11_LSN_UNSLCVC) | 964 GEN11_LSN_UNSLCVC,
864 GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC | 965 GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC |
865 GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC); 966 GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC);
866 967
867 /* Wa_220166154:icl 968 /* Wa_220166154:icl
868 * Formerly known as WaDisCtxReload 969 * Formerly known as WaDisCtxReload
869 */ 970 */
870 I915_WRITE(GEN8_GAMW_ECO_DEV_RW_IA, 971 wa_write_or(wal,
871 I915_READ(GEN8_GAMW_ECO_DEV_RW_IA) | 972 GEN8_GAMW_ECO_DEV_RW_IA,
872 GAMW_ECO_DEV_CTX_RELOAD_DISABLE); 973 GAMW_ECO_DEV_CTX_RELOAD_DISABLE);
873 974
874 /* Wa_1405779004:icl (pre-prod) */ 975 /* Wa_1405779004:icl (pre-prod) */
875 if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0)) 976 if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0))
876 I915_WRITE(SLICE_UNIT_LEVEL_CLKGATE, 977 wa_write_or(wal,
877 I915_READ(SLICE_UNIT_LEVEL_CLKGATE) | 978 SLICE_UNIT_LEVEL_CLKGATE,
878 MSCUNIT_CLKGATE_DIS); 979 MSCUNIT_CLKGATE_DIS);
879 980
880 /* Wa_1406680159:icl */ 981 /* Wa_1406680159:icl */
881 I915_WRITE(SUBSLICE_UNIT_LEVEL_CLKGATE, 982 wa_write_or(wal,
882 I915_READ(SUBSLICE_UNIT_LEVEL_CLKGATE) | 983 SUBSLICE_UNIT_LEVEL_CLKGATE,
883 GWUNIT_CLKGATE_DIS); 984 GWUNIT_CLKGATE_DIS);
884 985
885 /* Wa_1406838659:icl (pre-prod) */ 986 /* Wa_1406838659:icl (pre-prod) */
886 if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0)) 987 if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
887 I915_WRITE(INF_UNIT_LEVEL_CLKGATE, 988 wa_write_or(wal,
888 I915_READ(INF_UNIT_LEVEL_CLKGATE) | 989 INF_UNIT_LEVEL_CLKGATE,
889 CGPSF_CLKGATE_DIS); 990 CGPSF_CLKGATE_DIS);
890 991
891 /* WaForwardProgressSoftReset:icl */ 992 /* WaForwardProgressSoftReset:icl */
892 I915_WRITE(GEN10_SCRATCH_LNCF2, 993 wa_write_or(wal,
893 I915_READ(GEN10_SCRATCH_LNCF2) | 994 GEN10_SCRATCH_LNCF2,
894 PMFLUSHDONE_LNICRSDROP | 995 PMFLUSHDONE_LNICRSDROP |
895 PMFLUSH_GAPL3UNBLOCK | 996 PMFLUSH_GAPL3UNBLOCK |
896 PMFLUSHDONE_LNEBLK); 997 PMFLUSHDONE_LNEBLK);
897 998
898 /* Wa_1406463099:icl 999 /* Wa_1406463099:icl
899 * Formerly known as WaGamTlbPendError 1000 * Formerly known as WaGamTlbPendError
900 */ 1001 */
901 I915_WRITE(GAMT_CHKN_BIT_REG, 1002 wa_write_or(wal,
902 I915_READ(GAMT_CHKN_BIT_REG) | 1003 GAMT_CHKN_BIT_REG,
903 GAMT_CHKN_DISABLE_L3_COH_PIPE); 1004 GAMT_CHKN_DISABLE_L3_COH_PIPE);
904 1005
905 /* Wa_1406609255:icl (pre-prod) */ 1006 /* Wa_1406609255:icl (pre-prod) */
906 if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0)) 1007 if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0))
907 I915_WRITE(GEN7_SARCHKMD, 1008 wa_write_or(wal,
908 I915_READ(GEN7_SARCHKMD) | 1009 GEN7_SARCHKMD,
909 GEN7_DISABLE_DEMAND_PREFETCH | 1010 GEN7_DISABLE_DEMAND_PREFETCH |
910 GEN7_DISABLE_SAMPLER_PREFETCH); 1011 GEN7_DISABLE_SAMPLER_PREFETCH);
911} 1012}
912 1013
913void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) 1014void intel_gt_init_workarounds(struct drm_i915_private *i915)
914{ 1015{
915 if (INTEL_GEN(dev_priv) < 8) 1016 struct i915_wa_list *wal = &i915->gt_wa_list;
1017
1018 wa_init_start(wal, "GT");
1019
1020 if (INTEL_GEN(i915) < 8)
916 return; 1021 return;
917 else if (IS_BROADWELL(dev_priv)) 1022 else if (IS_BROADWELL(i915))
918 bdw_gt_workarounds_apply(dev_priv); 1023 return;
919 else if (IS_CHERRYVIEW(dev_priv)) 1024 else if (IS_CHERRYVIEW(i915))
920 chv_gt_workarounds_apply(dev_priv); 1025 return;
921 else if (IS_SKYLAKE(dev_priv)) 1026 else if (IS_SKYLAKE(i915))
922 skl_gt_workarounds_apply(dev_priv); 1027 skl_gt_workarounds_init(i915);
923 else if (IS_BROXTON(dev_priv)) 1028 else if (IS_BROXTON(i915))
924 bxt_gt_workarounds_apply(dev_priv); 1029 bxt_gt_workarounds_init(i915);
925 else if (IS_KABYLAKE(dev_priv)) 1030 else if (IS_KABYLAKE(i915))
926 kbl_gt_workarounds_apply(dev_priv); 1031 kbl_gt_workarounds_init(i915);
927 else if (IS_GEMINILAKE(dev_priv)) 1032 else if (IS_GEMINILAKE(i915))
928 glk_gt_workarounds_apply(dev_priv); 1033 glk_gt_workarounds_init(i915);
929 else if (IS_COFFEELAKE(dev_priv)) 1034 else if (IS_COFFEELAKE(i915))
930 cfl_gt_workarounds_apply(dev_priv); 1035 cfl_gt_workarounds_init(i915);
931 else if (IS_CANNONLAKE(dev_priv)) 1036 else if (IS_CANNONLAKE(i915))
932 cnl_gt_workarounds_apply(dev_priv); 1037 cnl_gt_workarounds_init(i915);
933 else if (IS_ICELAKE(dev_priv)) 1038 else if (IS_ICELAKE(i915))
934 icl_gt_workarounds_apply(dev_priv); 1039 icl_gt_workarounds_init(i915);
935 else 1040 else
936 MISSING_CASE(INTEL_GEN(dev_priv)); 1041 MISSING_CASE(INTEL_GEN(i915));
1042
1043 wa_init_finish(wal);
1044}
1045
1046static enum forcewake_domains
1047wal_get_fw_for_rmw(struct drm_i915_private *dev_priv,
1048 const struct i915_wa_list *wal)
1049{
1050 enum forcewake_domains fw = 0;
1051 struct i915_wa *wa;
1052 unsigned int i;
1053
1054 for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
1055 fw |= intel_uncore_forcewake_for_reg(dev_priv,
1056 wa->reg,
1057 FW_REG_READ |
1058 FW_REG_WRITE);
1059
1060 return fw;
1061}
1062
1063static void
1064wa_list_apply(struct drm_i915_private *dev_priv, const struct i915_wa_list *wal)
1065{
1066 enum forcewake_domains fw;
1067 unsigned long flags;
1068 struct i915_wa *wa;
1069 unsigned int i;
1070
1071 if (!wal->count)
1072 return;
1073
1074 fw = wal_get_fw_for_rmw(dev_priv, wal);
1075
1076 spin_lock_irqsave(&dev_priv->uncore.lock, flags);
1077 intel_uncore_forcewake_get__locked(dev_priv, fw);
1078
1079 for (i = 0, wa = wal->list; i < wal->count; i++, wa++) {
1080 u32 val = I915_READ_FW(wa->reg);
1081
1082 val &= ~wa->mask;
1083 val |= wa->val;
1084
1085 I915_WRITE_FW(wa->reg, val);
1086 }
1087
1088 intel_uncore_forcewake_put__locked(dev_priv, fw);
1089 spin_unlock_irqrestore(&dev_priv->uncore.lock, flags);
1090
1091 DRM_DEBUG_DRIVER("Applied %u %s workarounds\n", wal->count, wal->name);
1092}
1093
1094void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv)
1095{
1096 wa_list_apply(dev_priv, &dev_priv->gt_wa_list);
937} 1097}
938 1098
939struct whitelist { 1099struct whitelist {
diff --git a/drivers/gpu/drm/i915/intel_workarounds.h b/drivers/gpu/drm/i915/intel_workarounds.h
index b11d0623e626..263106600fdc 100644
--- a/drivers/gpu/drm/i915/intel_workarounds.h
+++ b/drivers/gpu/drm/i915/intel_workarounds.h
@@ -7,10 +7,31 @@
7#ifndef _I915_WORKAROUNDS_H_ 7#ifndef _I915_WORKAROUNDS_H_
8#define _I915_WORKAROUNDS_H_ 8#define _I915_WORKAROUNDS_H_
9 9
10#include <linux/slab.h>
11
12struct i915_wa {
13 i915_reg_t reg;
14 u32 mask;
15 u32 val;
16};
17
18struct i915_wa_list {
19 const char *name;
20 struct i915_wa *list;
21 unsigned int count;
22};
23
24static inline void intel_wa_list_free(struct i915_wa_list *wal)
25{
26 kfree(wal->list);
27 memset(wal, 0, sizeof(*wal));
28}
29
10int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv); 30int intel_ctx_workarounds_init(struct drm_i915_private *dev_priv);
11int intel_ctx_workarounds_emit(struct i915_request *rq); 31int intel_ctx_workarounds_emit(struct i915_request *rq);
12 32
13void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv); 33void intel_gt_init_workarounds(struct drm_i915_private *dev_priv);
34void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv);
14 35
15void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine); 36void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine);
16 37