linux/drivers/gpu/drm/i915/gt/intel_sseu.c
<<
>>
Prefs
   1/*
   2 * SPDX-License-Identifier: MIT
   3 *
   4 * Copyright © 2019 Intel Corporation
   5 */
   6
   7#include "i915_drv.h"
   8#include "intel_lrc_reg.h"
   9#include "intel_sseu.h"
  10
  11unsigned int
  12intel_sseu_subslice_total(const struct sseu_dev_info *sseu)
  13{
  14        unsigned int i, total = 0;
  15
  16        for (i = 0; i < ARRAY_SIZE(sseu->subslice_mask); i++)
  17                total += hweight8(sseu->subslice_mask[i]);
  18
  19        return total;
  20}
  21
  22unsigned int
  23intel_sseu_subslices_per_slice(const struct sseu_dev_info *sseu, u8 slice)
  24{
  25        return hweight8(sseu->subslice_mask[slice]);
  26}
  27
  28u32 intel_sseu_make_rpcs(struct drm_i915_private *i915,
  29                         const struct intel_sseu *req_sseu)
  30{
  31        const struct sseu_dev_info *sseu = &RUNTIME_INFO(i915)->sseu;
  32        bool subslice_pg = sseu->has_subslice_pg;
  33        struct intel_sseu ctx_sseu;
  34        u8 slices, subslices;
  35        u32 rpcs = 0;
  36
  37        /*
  38         * No explicit RPCS request is needed to ensure full
  39         * slice/subslice/EU enablement prior to Gen9.
  40         */
  41        if (INTEL_GEN(i915) < 9)
  42                return 0;
  43
  44        /*
  45         * If i915/perf is active, we want a stable powergating configuration
  46         * on the system.
  47         *
  48         * We could choose full enablement, but on ICL we know there are use
  49         * cases which disable slices for functional, apart for performance
  50         * reasons. So in this case we select a known stable subset.
  51         */
  52        if (!i915->perf.oa.exclusive_stream) {
  53                ctx_sseu = *req_sseu;
  54        } else {
  55                ctx_sseu = intel_sseu_from_device_info(sseu);
  56
  57                if (IS_GEN(i915, 11)) {
  58                        /*
  59                         * We only need subslice count so it doesn't matter
  60                         * which ones we select - just turn off low bits in the
  61                         * amount of half of all available subslices per slice.
  62                         */
  63                        ctx_sseu.subslice_mask =
  64                                ~(~0 << (hweight8(ctx_sseu.subslice_mask) / 2));
  65                        ctx_sseu.slice_mask = 0x1;
  66                }
  67        }
  68
  69        slices = hweight8(ctx_sseu.slice_mask);
  70        subslices = hweight8(ctx_sseu.subslice_mask);
  71
  72        /*
  73         * Since the SScount bitfield in GEN8_R_PWR_CLK_STATE is only three bits
  74         * wide and Icelake has up to eight subslices, specfial programming is
  75         * needed in order to correctly enable all subslices.
  76         *
  77         * According to documentation software must consider the configuration
  78         * as 2x4x8 and hardware will translate this to 1x8x8.
  79         *
  80         * Furthemore, even though SScount is three bits, maximum documented
  81         * value for it is four. From this some rules/restrictions follow:
  82         *
  83         * 1.
  84         * If enabled subslice count is greater than four, two whole slices must
  85         * be enabled instead.
  86         *
  87         * 2.
  88         * When more than one slice is enabled, hardware ignores the subslice
  89         * count altogether.
  90         *
  91         * From these restrictions it follows that it is not possible to enable
  92         * a count of subslices between the SScount maximum of four restriction,
  93         * and the maximum available number on a particular SKU. Either all
  94         * subslices are enabled, or a count between one and four on the first
  95         * slice.
  96         */
  97        if (IS_GEN(i915, 11) &&
  98            slices == 1 &&
  99            subslices > min_t(u8, 4, hweight8(sseu->subslice_mask[0]) / 2)) {
 100                GEM_BUG_ON(subslices & 1);
 101
 102                subslice_pg = false;
 103                slices *= 2;
 104        }
 105
 106        /*
 107         * Starting in Gen9, render power gating can leave
 108         * slice/subslice/EU in a partially enabled state. We
 109         * must make an explicit request through RPCS for full
 110         * enablement.
 111         */
 112        if (sseu->has_slice_pg) {
 113                u32 mask, val = slices;
 114
 115                if (INTEL_GEN(i915) >= 11) {
 116                        mask = GEN11_RPCS_S_CNT_MASK;
 117                        val <<= GEN11_RPCS_S_CNT_SHIFT;
 118                } else {
 119                        mask = GEN8_RPCS_S_CNT_MASK;
 120                        val <<= GEN8_RPCS_S_CNT_SHIFT;
 121                }
 122
 123                GEM_BUG_ON(val & ~mask);
 124                val &= mask;
 125
 126                rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_S_CNT_ENABLE | val;
 127        }
 128
 129        if (subslice_pg) {
 130                u32 val = subslices;
 131
 132                val <<= GEN8_RPCS_SS_CNT_SHIFT;
 133
 134                GEM_BUG_ON(val & ~GEN8_RPCS_SS_CNT_MASK);
 135                val &= GEN8_RPCS_SS_CNT_MASK;
 136
 137                rpcs |= GEN8_RPCS_ENABLE | GEN8_RPCS_SS_CNT_ENABLE | val;
 138        }
 139
 140        if (sseu->has_eu_pg) {
 141                u32 val;
 142
 143                val = ctx_sseu.min_eus_per_subslice << GEN8_RPCS_EU_MIN_SHIFT;
 144                GEM_BUG_ON(val & ~GEN8_RPCS_EU_MIN_MASK);
 145                val &= GEN8_RPCS_EU_MIN_MASK;
 146
 147                rpcs |= val;
 148
 149                val = ctx_sseu.max_eus_per_subslice << GEN8_RPCS_EU_MAX_SHIFT;
 150                GEM_BUG_ON(val & ~GEN8_RPCS_EU_MAX_MASK);
 151                val &= GEN8_RPCS_EU_MAX_MASK;
 152
 153                rpcs |= val;
 154
 155                rpcs |= GEN8_RPCS_ENABLE;
 156        }
 157
 158        return rpcs;
 159}
 160