diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_workarounds.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_workarounds.c | 591 |
1 files changed, 390 insertions, 201 deletions
diff --git a/drivers/gpu/drm/i915/intel_workarounds.c b/drivers/gpu/drm/i915/intel_workarounds.c index 4bcdeaf8d98f..6e580891db96 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 | ||
| 51 | static void wa_init_start(struct i915_wa_list *wal, const char *name) | ||
| 52 | { | ||
| 53 | wal->name = name; | ||
| 54 | } | ||
| 55 | |||
| 56 | static 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 | |||
| 51 | static void wa_add(struct drm_i915_private *i915, | 65 | static 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 | { |
| @@ -580,160 +594,175 @@ int intel_ctx_workarounds_emit(struct i915_request *rq) | |||
| 580 | return 0; | 594 | return 0; |
| 581 | } | 595 | } |
| 582 | 596 | ||
| 583 | static void bdw_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 597 | static void |
| 598 | wal_add(struct i915_wa_list *wal, const struct i915_wa *wa) | ||
| 599 | { | ||
| 600 | const unsigned int grow = 1 << 4; | ||
| 601 | |||
| 602 | GEM_BUG_ON(!is_power_of_2(grow)); | ||
| 603 | |||
| 604 | if (IS_ALIGNED(wal->count, grow)) { /* Either uninitialized or full. */ | ||
| 605 | struct i915_wa *list; | ||
| 606 | |||
| 607 | list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa), | ||
| 608 | GFP_KERNEL); | ||
| 609 | if (!list) { | ||
| 610 | DRM_ERROR("No space for workaround init!\n"); | ||
| 611 | return; | ||
| 612 | } | ||
| 613 | |||
| 614 | if (wal->list) | ||
| 615 | memcpy(list, wal->list, sizeof(*wa) * wal->count); | ||
| 616 | |||
| 617 | wal->list = list; | ||
| 618 | } | ||
| 619 | |||
| 620 | wal->list[wal->count++] = *wa; | ||
| 621 | } | ||
| 622 | |||
| 623 | static void | ||
| 624 | wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val) | ||
| 625 | { | ||
| 626 | struct i915_wa wa = { | ||
| 627 | .reg = reg, | ||
| 628 | .mask = val, | ||
| 629 | .val = _MASKED_BIT_ENABLE(val) | ||
| 630 | }; | ||
| 631 | |||
| 632 | wal_add(wal, &wa); | ||
| 633 | } | ||
| 634 | |||
| 635 | static void | ||
| 636 | wa_write_masked_or(struct i915_wa_list *wal, i915_reg_t reg, u32 mask, | ||
| 637 | u32 val) | ||
| 584 | { | 638 | { |
| 639 | struct i915_wa wa = { | ||
| 640 | .reg = reg, | ||
| 641 | .mask = mask, | ||
| 642 | .val = val | ||
| 643 | }; | ||
| 644 | |||
| 645 | wal_add(wal, &wa); | ||
| 585 | } | 646 | } |
| 586 | 647 | ||
| 587 | static void chv_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 648 | static void |
| 649 | wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 val) | ||
| 588 | { | 650 | { |
| 651 | wa_write_masked_or(wal, reg, ~0, val); | ||
| 589 | } | 652 | } |
| 590 | 653 | ||
| 591 | static void gen9_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 654 | static void |
| 655 | wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 val) | ||
| 592 | { | 656 | { |
| 593 | /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */ | 657 | wa_write_masked_or(wal, reg, val, val); |
| 594 | I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, | 658 | } |
| 595 | _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); | ||
| 596 | 659 | ||
| 597 | /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */ | 660 | static void gen9_gt_workarounds_init(struct drm_i915_private *i915) |
| 598 | I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | | 661 | { |
| 599 | GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); | 662 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 600 | 663 | ||
| 601 | /* WaDisableKillLogic:bxt,skl,kbl */ | 664 | /* WaDisableKillLogic:bxt,skl,kbl */ |
| 602 | if (!IS_COFFEELAKE(dev_priv)) | 665 | if (!IS_COFFEELAKE(i915)) |
| 603 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | | 666 | wa_write_or(wal, |
| 604 | ECOCHK_DIS_TLB); | 667 | GAM_ECOCHK, |
| 668 | ECOCHK_DIS_TLB); | ||
| 605 | 669 | ||
| 606 | if (HAS_LLC(dev_priv)) { | 670 | if (HAS_LLC(i915)) { |
| 607 | /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl | 671 | /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl |
| 608 | * | 672 | * |
| 609 | * Must match Display Engine. See | 673 | * Must match Display Engine. See |
| 610 | * WaCompressedResourceDisplayNewHashMode. | 674 | * WaCompressedResourceDisplayNewHashMode. |
| 611 | */ | 675 | */ |
| 612 | I915_WRITE(MMCD_MISC_CTRL, | 676 | wa_write_or(wal, |
| 613 | I915_READ(MMCD_MISC_CTRL) | | 677 | MMCD_MISC_CTRL, |
| 614 | MMCD_PCLA | | 678 | MMCD_PCLA | MMCD_HOTSPOT_EN); |
| 615 | MMCD_HOTSPOT_EN); | ||
| 616 | } | 679 | } |
| 617 | 680 | ||
| 618 | /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */ | 681 | /* WaDisableHDCInvalidation:skl,bxt,kbl,cfl */ |
| 619 | I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | | 682 | wa_write_or(wal, |
| 620 | BDW_DISABLE_HDC_INVALIDATION); | 683 | GAM_ECOCHK, |
| 621 | 684 | BDW_DISABLE_HDC_INVALIDATION); | |
| 622 | /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */ | ||
| 623 | if (IS_GEN9_LP(dev_priv)) { | ||
| 624 | u32 val = I915_READ(GEN8_L3SQCREG1); | ||
| 625 | |||
| 626 | val &= ~L3_PRIO_CREDITS_MASK; | ||
| 627 | val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); | ||
| 628 | I915_WRITE(GEN8_L3SQCREG1, val); | ||
| 629 | } | ||
| 630 | |||
| 631 | /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */ | ||
| 632 | I915_WRITE(GEN8_L3SQCREG4, | ||
| 633 | I915_READ(GEN8_L3SQCREG4) | GEN8_LQSC_FLUSH_COHERENT_LINES); | ||
| 634 | |||
| 635 | /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ | ||
| 636 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, | ||
| 637 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | ||
| 638 | } | 685 | } |
| 639 | 686 | ||
| 640 | static void skl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 687 | static void skl_gt_workarounds_init(struct drm_i915_private *i915) |
| 641 | { | 688 | { |
| 642 | gen9_gt_workarounds_apply(dev_priv); | 689 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 643 | 690 | ||
| 644 | /* WaEnableGapsTsvCreditFix:skl */ | 691 | gen9_gt_workarounds_init(i915); |
| 645 | I915_WRITE(GEN8_GARBCNTL, | ||
| 646 | I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); | ||
| 647 | 692 | ||
| 648 | /* WaDisableGafsUnitClkGating:skl */ | 693 | /* WaDisableGafsUnitClkGating:skl */ |
| 649 | I915_WRITE(GEN7_UCGCTL4, | 694 | wa_write_or(wal, |
| 650 | I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | 695 | GEN7_UCGCTL4, |
| 696 | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | ||
| 651 | 697 | ||
| 652 | /* WaInPlaceDecompressionHang:skl */ | 698 | /* WaInPlaceDecompressionHang:skl */ |
| 653 | if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) | 699 | if (IS_SKL_REVID(i915, SKL_REVID_H0, REVID_FOREVER)) |
| 654 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | 700 | wa_write_or(wal, |
| 655 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | 701 | GEN9_GAMT_ECO_REG_RW_IA, |
| 656 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | 702 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); |
| 657 | } | 703 | } |
| 658 | 704 | ||
| 659 | static void bxt_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 705 | static void bxt_gt_workarounds_init(struct drm_i915_private *i915) |
| 660 | { | 706 | { |
| 661 | gen9_gt_workarounds_apply(dev_priv); | 707 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 662 | 708 | ||
| 663 | /* WaDisablePooledEuLoadBalancingFix:bxt */ | 709 | gen9_gt_workarounds_init(i915); |
| 664 | I915_WRITE(FF_SLICE_CS_CHICKEN2, | ||
| 665 | _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); | ||
| 666 | 710 | ||
| 667 | /* WaInPlaceDecompressionHang:bxt */ | 711 | /* WaInPlaceDecompressionHang:bxt */ |
| 668 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | 712 | wa_write_or(wal, |
| 669 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | 713 | GEN9_GAMT_ECO_REG_RW_IA, |
| 670 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | 714 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); |
| 671 | } | 715 | } |
| 672 | 716 | ||
| 673 | static void kbl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 717 | static void kbl_gt_workarounds_init(struct drm_i915_private *i915) |
| 674 | { | 718 | { |
| 675 | gen9_gt_workarounds_apply(dev_priv); | 719 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 676 | 720 | ||
| 677 | /* WaEnableGapsTsvCreditFix:kbl */ | 721 | gen9_gt_workarounds_init(i915); |
| 678 | I915_WRITE(GEN8_GARBCNTL, | ||
| 679 | I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); | ||
| 680 | 722 | ||
| 681 | /* WaDisableDynamicCreditSharing:kbl */ | 723 | /* WaDisableDynamicCreditSharing:kbl */ |
| 682 | if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) | 724 | if (IS_KBL_REVID(i915, 0, KBL_REVID_B0)) |
| 683 | I915_WRITE(GAMT_CHKN_BIT_REG, | 725 | wa_write_or(wal, |
| 684 | I915_READ(GAMT_CHKN_BIT_REG) | | 726 | GAMT_CHKN_BIT_REG, |
| 685 | GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); | 727 | GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); |
| 686 | 728 | ||
| 687 | /* WaDisableGafsUnitClkGating:kbl */ | 729 | /* WaDisableGafsUnitClkGating:kbl */ |
| 688 | I915_WRITE(GEN7_UCGCTL4, | 730 | wa_write_or(wal, |
| 689 | I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | 731 | GEN7_UCGCTL4, |
| 732 | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | ||
| 690 | 733 | ||
| 691 | /* WaInPlaceDecompressionHang:kbl */ | 734 | /* WaInPlaceDecompressionHang:kbl */ |
| 692 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | 735 | wa_write_or(wal, |
| 693 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | 736 | GEN9_GAMT_ECO_REG_RW_IA, |
| 694 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | 737 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); |
| 695 | |||
| 696 | /* WaKBLVECSSemaphoreWaitPoll:kbl */ | ||
| 697 | if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_E0)) { | ||
| 698 | struct intel_engine_cs *engine; | ||
| 699 | unsigned int tmp; | ||
| 700 | |||
| 701 | for_each_engine(engine, dev_priv, tmp) { | ||
| 702 | if (engine->id == RCS) | ||
| 703 | continue; | ||
| 704 | |||
| 705 | I915_WRITE(RING_SEMA_WAIT_POLL(engine->mmio_base), 1); | ||
| 706 | } | ||
| 707 | } | ||
| 708 | } | 738 | } |
| 709 | 739 | ||
| 710 | static void glk_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 740 | static void glk_gt_workarounds_init(struct drm_i915_private *i915) |
| 711 | { | 741 | { |
| 712 | gen9_gt_workarounds_apply(dev_priv); | 742 | gen9_gt_workarounds_init(i915); |
| 713 | } | 743 | } |
| 714 | 744 | ||
| 715 | static void cfl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 745 | static void cfl_gt_workarounds_init(struct drm_i915_private *i915) |
| 716 | { | 746 | { |
| 717 | gen9_gt_workarounds_apply(dev_priv); | 747 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 718 | 748 | ||
| 719 | /* WaEnableGapsTsvCreditFix:cfl */ | 749 | gen9_gt_workarounds_init(i915); |
| 720 | I915_WRITE(GEN8_GARBCNTL, | ||
| 721 | I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE); | ||
| 722 | 750 | ||
| 723 | /* WaDisableGafsUnitClkGating:cfl */ | 751 | /* WaDisableGafsUnitClkGating:cfl */ |
| 724 | I915_WRITE(GEN7_UCGCTL4, | 752 | wa_write_or(wal, |
| 725 | I915_READ(GEN7_UCGCTL4) | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | 753 | GEN7_UCGCTL4, |
| 754 | GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | ||
| 726 | 755 | ||
| 727 | /* WaInPlaceDecompressionHang:cfl */ | 756 | /* WaInPlaceDecompressionHang:cfl */ |
| 728 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | 757 | wa_write_or(wal, |
| 729 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | 758 | GEN9_GAMT_ECO_REG_RW_IA, |
| 730 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | 759 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); |
| 731 | } | 760 | } |
| 732 | 761 | ||
| 733 | static void wa_init_mcr(struct drm_i915_private *dev_priv) | 762 | static void wa_init_mcr(struct drm_i915_private *dev_priv) |
| 734 | { | 763 | { |
| 735 | const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu); | 764 | const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu); |
| 736 | u32 mcr; | 765 | struct i915_wa_list *wal = &dev_priv->gt_wa_list; |
| 737 | u32 mcr_slice_subslice_mask; | 766 | u32 mcr_slice_subslice_mask; |
| 738 | 767 | ||
| 739 | /* | 768 | /* |
| @@ -770,8 +799,6 @@ static void wa_init_mcr(struct drm_i915_private *dev_priv) | |||
| 770 | WARN_ON((enabled_mask & disabled_mask) != enabled_mask); | 799 | WARN_ON((enabled_mask & disabled_mask) != enabled_mask); |
| 771 | } | 800 | } |
| 772 | 801 | ||
| 773 | mcr = I915_READ(GEN8_MCR_SELECTOR); | ||
| 774 | |||
| 775 | if (INTEL_GEN(dev_priv) >= 11) | 802 | if (INTEL_GEN(dev_priv) >= 11) |
| 776 | mcr_slice_subslice_mask = GEN11_MCR_SLICE_MASK | | 803 | mcr_slice_subslice_mask = GEN11_MCR_SLICE_MASK | |
| 777 | GEN11_MCR_SUBSLICE_MASK; | 804 | GEN11_MCR_SUBSLICE_MASK; |
| @@ -789,148 +816,170 @@ static void wa_init_mcr(struct drm_i915_private *dev_priv) | |||
| 789 | * occasions, such as INSTDONE, where this value is dependent | 816 | * occasions, such as INSTDONE, where this value is dependent |
| 790 | * on s/ss combo, the read should be done with read_subslice_reg. | 817 | * on s/ss combo, the read should be done with read_subslice_reg. |
| 791 | */ | 818 | */ |
| 792 | mcr &= ~mcr_slice_subslice_mask; | 819 | wa_write_masked_or(wal, |
| 793 | mcr |= intel_calculate_mcr_s_ss_select(dev_priv); | 820 | GEN8_MCR_SELECTOR, |
| 794 | I915_WRITE(GEN8_MCR_SELECTOR, mcr); | 821 | mcr_slice_subslice_mask, |
| 822 | intel_calculate_mcr_s_ss_select(dev_priv)); | ||
| 795 | } | 823 | } |
| 796 | 824 | ||
| 797 | static void cnl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 825 | static void cnl_gt_workarounds_init(struct drm_i915_private *i915) |
| 798 | { | 826 | { |
| 799 | wa_init_mcr(dev_priv); | 827 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 828 | |||
| 829 | wa_init_mcr(i915); | ||
| 800 | 830 | ||
| 801 | /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ | 831 | /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ |
| 802 | if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) | 832 | if (IS_CNL_REVID(i915, CNL_REVID_B0, CNL_REVID_B0)) |
| 803 | I915_WRITE(GAMT_CHKN_BIT_REG, | 833 | wa_write_or(wal, |
| 804 | I915_READ(GAMT_CHKN_BIT_REG) | | 834 | GAMT_CHKN_BIT_REG, |
| 805 | GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); | 835 | GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); |
| 806 | 836 | ||
| 807 | /* WaInPlaceDecompressionHang:cnl */ | 837 | /* WaInPlaceDecompressionHang:cnl */ |
| 808 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, | 838 | wa_write_or(wal, |
| 809 | I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | 839 | GEN9_GAMT_ECO_REG_RW_IA, |
| 810 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | 840 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); |
| 811 | |||
| 812 | /* WaEnablePreemptionGranularityControlByUMD:cnl */ | ||
| 813 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, | ||
| 814 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | ||
| 815 | } | 841 | } |
| 816 | 842 | ||
| 817 | static void icl_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 843 | static void icl_gt_workarounds_init(struct drm_i915_private *i915) |
| 818 | { | 844 | { |
| 819 | wa_init_mcr(dev_priv); | 845 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 820 | 846 | ||
| 821 | /* This is not an Wa. Enable for better image quality */ | 847 | wa_init_mcr(i915); |
| 822 | I915_WRITE(_3D_CHICKEN3, | ||
| 823 | _MASKED_BIT_ENABLE(_3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE)); | ||
| 824 | 848 | ||
| 825 | /* WaInPlaceDecompressionHang:icl */ | 849 | /* WaInPlaceDecompressionHang:icl */ |
| 826 | I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | | 850 | wa_write_or(wal, |
| 827 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | 851 | GEN9_GAMT_ECO_REG_RW_IA, |
| 828 | 852 | GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); | |
| 829 | /* WaPipelineFlushCoherentLines:icl */ | ||
| 830 | I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | | ||
| 831 | GEN8_LQSC_FLUSH_COHERENT_LINES); | ||
| 832 | |||
| 833 | /* Wa_1405543622:icl | ||
| 834 | * Formerly known as WaGAPZPriorityScheme | ||
| 835 | */ | ||
| 836 | I915_WRITE(GEN8_GARBCNTL, I915_READ(GEN8_GARBCNTL) | | ||
| 837 | GEN11_ARBITRATION_PRIO_ORDER_MASK); | ||
| 838 | |||
| 839 | /* Wa_1604223664:icl | ||
| 840 | * Formerly known as WaL3BankAddressHashing | ||
| 841 | */ | ||
| 842 | I915_WRITE(GEN8_GARBCNTL, | ||
| 843 | (I915_READ(GEN8_GARBCNTL) & ~GEN11_HASH_CTRL_EXCL_MASK) | | ||
| 844 | GEN11_HASH_CTRL_EXCL_BIT0); | ||
| 845 | I915_WRITE(GEN11_GLBLINVL, | ||
| 846 | (I915_READ(GEN11_GLBLINVL) & ~GEN11_BANK_HASH_ADDR_EXCL_MASK) | | ||
| 847 | GEN11_BANK_HASH_ADDR_EXCL_BIT0); | ||
| 848 | 853 | ||
| 849 | /* WaModifyGamTlbPartitioning:icl */ | 854 | /* WaModifyGamTlbPartitioning:icl */ |
| 850 | I915_WRITE(GEN11_GACB_PERF_CTRL, | 855 | wa_write_masked_or(wal, |
| 851 | (I915_READ(GEN11_GACB_PERF_CTRL) & ~GEN11_HASH_CTRL_MASK) | | 856 | GEN11_GACB_PERF_CTRL, |
| 852 | GEN11_HASH_CTRL_BIT0 | GEN11_HASH_CTRL_BIT4); | 857 | GEN11_HASH_CTRL_MASK, |
| 853 | 858 | GEN11_HASH_CTRL_BIT0 | GEN11_HASH_CTRL_BIT4); | |
| 854 | /* Wa_1405733216:icl | ||
| 855 | * Formerly known as WaDisableCleanEvicts | ||
| 856 | */ | ||
| 857 | I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | | ||
| 858 | GEN11_LQSC_CLEAN_EVICT_DISABLE); | ||
| 859 | 859 | ||
| 860 | /* Wa_1405766107:icl | 860 | /* Wa_1405766107:icl |
| 861 | * Formerly known as WaCL2SFHalfMaxAlloc | 861 | * Formerly known as WaCL2SFHalfMaxAlloc |
| 862 | */ | 862 | */ |
| 863 | I915_WRITE(GEN11_LSN_UNSLCVC, I915_READ(GEN11_LSN_UNSLCVC) | | 863 | wa_write_or(wal, |
| 864 | GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC | | 864 | GEN11_LSN_UNSLCVC, |
| 865 | GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC); | 865 | GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC | |
| 866 | GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC); | ||
| 866 | 867 | ||
| 867 | /* Wa_220166154:icl | 868 | /* Wa_220166154:icl |
| 868 | * Formerly known as WaDisCtxReload | 869 | * Formerly known as WaDisCtxReload |
| 869 | */ | 870 | */ |
| 870 | I915_WRITE(GAMW_ECO_DEV_RW_IA_REG, I915_READ(GAMW_ECO_DEV_RW_IA_REG) | | 871 | wa_write_or(wal, |
| 871 | GAMW_ECO_DEV_CTX_RELOAD_DISABLE); | 872 | GEN8_GAMW_ECO_DEV_RW_IA, |
| 873 | GAMW_ECO_DEV_CTX_RELOAD_DISABLE); | ||
| 872 | 874 | ||
| 873 | /* Wa_1405779004:icl (pre-prod) */ | 875 | /* Wa_1405779004:icl (pre-prod) */ |
| 874 | if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_A0)) | 876 | if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_A0)) |
| 875 | I915_WRITE(SLICE_UNIT_LEVEL_CLKGATE, | 877 | wa_write_or(wal, |
| 876 | I915_READ(SLICE_UNIT_LEVEL_CLKGATE) | | 878 | SLICE_UNIT_LEVEL_CLKGATE, |
| 877 | MSCUNIT_CLKGATE_DIS); | 879 | MSCUNIT_CLKGATE_DIS); |
| 878 | 880 | ||
| 879 | /* Wa_1406680159:icl */ | 881 | /* Wa_1406680159:icl */ |
| 880 | I915_WRITE(SUBSLICE_UNIT_LEVEL_CLKGATE, | 882 | wa_write_or(wal, |
| 881 | I915_READ(SUBSLICE_UNIT_LEVEL_CLKGATE) | | 883 | SUBSLICE_UNIT_LEVEL_CLKGATE, |
| 882 | GWUNIT_CLKGATE_DIS); | 884 | GWUNIT_CLKGATE_DIS); |
| 883 | |||
| 884 | /* Wa_1604302699:icl */ | ||
| 885 | I915_WRITE(GEN10_L3_CHICKEN_MODE_REGISTER, | ||
| 886 | I915_READ(GEN10_L3_CHICKEN_MODE_REGISTER) | | ||
| 887 | GEN11_I2M_WRITE_DISABLE); | ||
| 888 | 885 | ||
| 889 | /* Wa_1406838659:icl (pre-prod) */ | 886 | /* Wa_1406838659:icl (pre-prod) */ |
| 890 | if (IS_ICL_REVID(dev_priv, ICL_REVID_A0, ICL_REVID_B0)) | 887 | if (IS_ICL_REVID(i915, ICL_REVID_A0, ICL_REVID_B0)) |
| 891 | I915_WRITE(INF_UNIT_LEVEL_CLKGATE, | 888 | wa_write_or(wal, |
| 892 | I915_READ(INF_UNIT_LEVEL_CLKGATE) | | 889 | INF_UNIT_LEVEL_CLKGATE, |
| 893 | CGPSF_CLKGATE_DIS); | 890 | CGPSF_CLKGATE_DIS); |
| 894 | |||
| 895 | /* WaForwardProgressSoftReset:icl */ | ||
| 896 | I915_WRITE(GEN10_SCRATCH_LNCF2, | ||
| 897 | I915_READ(GEN10_SCRATCH_LNCF2) | | ||
| 898 | PMFLUSHDONE_LNICRSDROP | | ||
| 899 | PMFLUSH_GAPL3UNBLOCK | | ||
| 900 | PMFLUSHDONE_LNEBLK); | ||
| 901 | 891 | ||
| 902 | /* Wa_1406463099:icl | 892 | /* Wa_1406463099:icl |
| 903 | * Formerly known as WaGamTlbPendError | 893 | * Formerly known as WaGamTlbPendError |
| 904 | */ | 894 | */ |
| 905 | I915_WRITE(GAMT_CHKN_BIT_REG, | 895 | wa_write_or(wal, |
| 906 | I915_READ(GAMT_CHKN_BIT_REG) | | 896 | GAMT_CHKN_BIT_REG, |
| 907 | GAMT_CHKN_DISABLE_L3_COH_PIPE); | 897 | GAMT_CHKN_DISABLE_L3_COH_PIPE); |
| 908 | } | 898 | } |
| 909 | 899 | ||
| 910 | void intel_gt_workarounds_apply(struct drm_i915_private *dev_priv) | 900 | void intel_gt_init_workarounds(struct drm_i915_private *i915) |
| 911 | { | 901 | { |
| 912 | if (INTEL_GEN(dev_priv) < 8) | 902 | struct i915_wa_list *wal = &i915->gt_wa_list; |
| 903 | |||
| 904 | wa_init_start(wal, "GT"); | ||
| 905 | |||
| 906 | if (INTEL_GEN(i915) < 8) | ||
| 913 | return; | 907 | return; |
| 914 | else if (IS_BROADWELL(dev_priv)) | 908 | else if (IS_BROADWELL(i915)) |
| 915 | bdw_gt_workarounds_apply(dev_priv); | 909 | return; |
| 916 | else if (IS_CHERRYVIEW(dev_priv)) | 910 | else if (IS_CHERRYVIEW(i915)) |
| 917 | chv_gt_workarounds_apply(dev_priv); | 911 | return; |
| 918 | else if (IS_SKYLAKE(dev_priv)) | 912 | else if (IS_SKYLAKE(i915)) |
| 919 | skl_gt_workarounds_apply(dev_priv); | 913 | skl_gt_workarounds_init(i915); |
| 920 | else if (IS_BROXTON(dev_priv)) | 914 | else if (IS_BROXTON(i915)) |
| 921 | bxt_gt_workarounds_apply(dev_priv); | 915 | bxt_gt_workarounds_init(i915); |
| 922 | else if (IS_KABYLAKE(dev_priv)) | 916 | else if (IS_KABYLAKE(i915)) |
| 923 | kbl_gt_workarounds_apply(dev_priv); | 917 | kbl_gt_workarounds_init(i915); |
| 924 | else if (IS_GEMINILAKE(dev_priv)) | 918 | else if (IS_GEMINILAKE(i915)) |
| 925 | glk_gt_workarounds_apply(dev_priv); | 919 | glk_gt_workarounds_init(i915); |
| 926 | else if (IS_COFFEELAKE(dev_priv)) | 920 | else if (IS_COFFEELAKE(i915)) |
| 927 | cfl_gt_workarounds_apply(dev_priv); | 921 | cfl_gt_workarounds_init(i915); |
| 928 | else if (IS_CANNONLAKE(dev_priv)) | 922 | else if (IS_CANNONLAKE(i915)) |
| 929 | cnl_gt_workarounds_apply(dev_priv); | 923 | cnl_gt_workarounds_init(i915); |
| 930 | else if (IS_ICELAKE(dev_priv)) | 924 | else if (IS_ICELAKE(i915)) |
| 931 | icl_gt_workarounds_apply(dev_priv); | 925 | icl_gt_workarounds_init(i915); |
| 932 | else | 926 | else |
| 933 | MISSING_CASE(INTEL_GEN(dev_priv)); | 927 | MISSING_CASE(INTEL_GEN(i915)); |
| 928 | |||
| 929 | wa_init_finish(wal); | ||
| 930 | } | ||
| 931 | |||
| 932 | static enum forcewake_domains | ||
| 933 | wal_get_fw_for_rmw(struct drm_i915_private *dev_priv, | ||
| 934 | const struct i915_wa_list *wal) | ||
| 935 | { | ||
| 936 | enum forcewake_domains fw = 0; | ||
| 937 | struct i915_wa *wa; | ||
| 938 | unsigned int i; | ||
| 939 | |||
| 940 | for (i = 0, wa = wal->list; i < wal->count; i++, wa++) | ||
| 941 | fw |= intel_uncore_forcewake_for_reg(dev_priv, | ||
| 942 | wa->reg, | ||
| 943 | FW_REG_READ | | ||
| 944 | FW_REG_WRITE); | ||
| 945 | |||
| 946 | return fw; | ||
| 947 | } | ||
| 948 | |||
| 949 | static void | ||
| 950 | wa_list_apply(struct drm_i915_private *dev_priv, const struct i915_wa_list *wal) | ||
| 951 | { | ||
| 952 | enum forcewake_domains fw; | ||
| 953 | unsigned long flags; | ||
| 954 | struct i915_wa *wa; | ||
| 955 | unsigned int i; | ||
| 956 | |||
| 957 | if (!wal->count) | ||
| 958 | return; | ||
| 959 | |||
| 960 | fw = wal_get_fw_for_rmw(dev_priv, wal); | ||
| 961 | |||
| 962 | spin_lock_irqsave(&dev_priv->uncore.lock, flags); | ||
| 963 | intel_uncore_forcewake_get__locked(dev_priv, fw); | ||
| 964 | |||
| 965 | for (i = 0, wa = wal->list; i < wal->count; i++, wa++) { | ||
| 966 | u32 val = I915_READ_FW(wa->reg); | ||
| 967 | |||
| 968 | val &= ~wa->mask; | ||
| 969 | val |= wa->val; | ||
| 970 | |||
| 971 | I915_WRITE_FW(wa->reg, val); | ||
| 972 | } | ||
| 973 | |||
| 974 | intel_uncore_forcewake_put__locked(dev_priv, fw); | ||
| 975 | spin_unlock_irqrestore(&dev_priv->uncore.lock, flags); | ||
| 976 | |||
| 977 | DRM_DEBUG_DRIVER("Applied %u %s workarounds\n", wal->count, wal->name); | ||
| 978 | } | ||
| 979 | |||
| 980 | void intel_gt_apply_workarounds(struct drm_i915_private *dev_priv) | ||
| 981 | { | ||
| 982 | wa_list_apply(dev_priv, &dev_priv->gt_wa_list); | ||
| 934 | } | 983 | } |
| 935 | 984 | ||
| 936 | struct whitelist { | 985 | struct whitelist { |
| @@ -1077,6 +1126,146 @@ void intel_whitelist_workarounds_apply(struct intel_engine_cs *engine) | |||
| 1077 | whitelist_apply(engine, whitelist_build(engine, &w)); | 1126 | whitelist_apply(engine, whitelist_build(engine, &w)); |
| 1078 | } | 1127 | } |
| 1079 | 1128 | ||
| 1129 | static void rcs_engine_wa_init(struct intel_engine_cs *engine) | ||
| 1130 | { | ||
| 1131 | struct drm_i915_private *i915 = engine->i915; | ||
| 1132 | struct i915_wa_list *wal = &engine->wa_list; | ||
| 1133 | |||
| 1134 | if (IS_ICELAKE(i915)) { | ||
| 1135 | /* This is not an Wa. Enable for better image quality */ | ||
| 1136 | wa_masked_en(wal, | ||
| 1137 | _3D_CHICKEN3, | ||
| 1138 | _3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE); | ||
| 1139 | |||
| 1140 | /* WaPipelineFlushCoherentLines:icl */ | ||
| 1141 | wa_write_or(wal, | ||
| 1142 | GEN8_L3SQCREG4, | ||
| 1143 | GEN8_LQSC_FLUSH_COHERENT_LINES); | ||
| 1144 | |||
| 1145 | /* | ||
| 1146 | * Wa_1405543622:icl | ||
| 1147 | * Formerly known as WaGAPZPriorityScheme | ||
| 1148 | */ | ||
| 1149 | wa_write_or(wal, | ||
| 1150 | GEN8_GARBCNTL, | ||
| 1151 | GEN11_ARBITRATION_PRIO_ORDER_MASK); | ||
| 1152 | |||
| 1153 | /* | ||
| 1154 | * Wa_1604223664:icl | ||
| 1155 | * Formerly known as WaL3BankAddressHashing | ||
| 1156 | */ | ||
| 1157 | wa_write_masked_or(wal, | ||
| 1158 | GEN8_GARBCNTL, | ||
| 1159 | GEN11_HASH_CTRL_EXCL_MASK, | ||
| 1160 | GEN11_HASH_CTRL_EXCL_BIT0); | ||
| 1161 | wa_write_masked_or(wal, | ||
| 1162 | GEN11_GLBLINVL, | ||
| 1163 | GEN11_BANK_HASH_ADDR_EXCL_MASK, | ||
| 1164 | GEN11_BANK_HASH_ADDR_EXCL_BIT0); | ||
| 1165 | |||
| 1166 | /* | ||
| 1167 | * Wa_1405733216:icl | ||
| 1168 | * Formerly known as WaDisableCleanEvicts | ||
| 1169 | */ | ||
| 1170 | wa_write_or(wal, | ||
| 1171 | GEN8_L3SQCREG4, | ||
| 1172 | GEN11_LQSC_CLEAN_EVICT_DISABLE); | ||
| 1173 | |||
| 1174 | /* Wa_1604302699:icl */ | ||
| 1175 | wa_write_or(wal, | ||
| 1176 | GEN10_L3_CHICKEN_MODE_REGISTER, | ||
| 1177 | GEN11_I2M_WRITE_DISABLE); | ||
| 1178 | |||
| 1179 | /* WaForwardProgressSoftReset:icl */ | ||
| 1180 | wa_write_or(wal, | ||
| 1181 | GEN10_SCRATCH_LNCF2, | ||
| 1182 | PMFLUSHDONE_LNICRSDROP | | ||
| 1183 | PMFLUSH_GAPL3UNBLOCK | | ||
| 1184 | PMFLUSHDONE_LNEBLK); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | if (IS_GEN9(i915) || IS_CANNONLAKE(i915)) { | ||
| 1188 | /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,cnl */ | ||
| 1189 | wa_masked_en(wal, | ||
| 1190 | GEN7_FF_SLICE_CS_CHICKEN1, | ||
| 1191 | GEN9_FFSC_PERCTX_PREEMPT_CTRL); | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | if (IS_SKYLAKE(i915) || IS_KABYLAKE(i915) || IS_COFFEELAKE(i915)) { | ||
| 1195 | /* WaEnableGapsTsvCreditFix:skl,kbl,cfl */ | ||
| 1196 | wa_write_or(wal, | ||
| 1197 | GEN8_GARBCNTL, | ||
| 1198 | GEN9_GAPS_TSV_CREDIT_DISABLE); | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | if (IS_BROXTON(i915)) { | ||
| 1202 | /* WaDisablePooledEuLoadBalancingFix:bxt */ | ||
| 1203 | wa_masked_en(wal, | ||
| 1204 | FF_SLICE_CS_CHICKEN2, | ||
| 1205 | GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | if (IS_GEN9(i915)) { | ||
| 1209 | /* WaContextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk,cfl */ | ||
| 1210 | wa_masked_en(wal, | ||
| 1211 | GEN9_CSFE_CHICKEN1_RCS, | ||
| 1212 | GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE); | ||
| 1213 | |||
| 1214 | /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */ | ||
| 1215 | wa_write_or(wal, | ||
| 1216 | BDW_SCRATCH1, | ||
| 1217 | GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); | ||
| 1218 | |||
| 1219 | /* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */ | ||
| 1220 | if (IS_GEN9_LP(i915)) | ||
| 1221 | wa_write_masked_or(wal, | ||
| 1222 | GEN8_L3SQCREG1, | ||
| 1223 | L3_PRIO_CREDITS_MASK, | ||
| 1224 | L3_GENERAL_PRIO_CREDITS(62) | | ||
| 1225 | L3_HIGH_PRIO_CREDITS(2)); | ||
| 1226 | |||
| 1227 | /* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */ | ||
| 1228 | wa_write_or(wal, | ||
| 1229 | GEN8_L3SQCREG4, | ||
| 1230 | GEN8_LQSC_FLUSH_COHERENT_LINES); | ||
| 1231 | } | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | static void xcs_engine_wa_init(struct intel_engine_cs *engine) | ||
| 1235 | { | ||
| 1236 | struct drm_i915_private *i915 = engine->i915; | ||
| 1237 | struct i915_wa_list *wal = &engine->wa_list; | ||
| 1238 | |||
| 1239 | /* WaKBLVECSSemaphoreWaitPoll:kbl */ | ||
| 1240 | if (IS_KBL_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) { | ||
| 1241 | wa_write(wal, | ||
| 1242 | RING_SEMA_WAIT_POLL(engine->mmio_base), | ||
| 1243 | 1); | ||
| 1244 | } | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | void intel_engine_init_workarounds(struct intel_engine_cs *engine) | ||
| 1248 | { | ||
| 1249 | struct i915_wa_list *wal = &engine->wa_list; | ||
| 1250 | |||
| 1251 | if (GEM_WARN_ON(INTEL_GEN(engine->i915) < 8)) | ||
| 1252 | return; | ||
| 1253 | |||
| 1254 | wa_init_start(wal, engine->name); | ||
| 1255 | |||
| 1256 | if (engine->id == RCS) | ||
| 1257 | rcs_engine_wa_init(engine); | ||
| 1258 | else | ||
| 1259 | xcs_engine_wa_init(engine); | ||
| 1260 | |||
| 1261 | wa_init_finish(wal); | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | void intel_engine_apply_workarounds(struct intel_engine_cs *engine) | ||
| 1265 | { | ||
| 1266 | wa_list_apply(engine->i915, &engine->wa_list); | ||
| 1267 | } | ||
| 1268 | |||
| 1080 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) | 1269 | #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) |
| 1081 | #include "selftests/intel_workarounds.c" | 1270 | #include "selftests/intel_workarounds.c" |
| 1082 | #endif | 1271 | #endif |
