2019-04-24 10:51:34 +01:00
/*
* SPDX - License - Identifier : MIT
*
* Copyright © 2019 Intel Corporation
*/
# include "i915_drv.h"
# include "intel_lrc_reg.h"
# include "intel_sseu.h"
2019-08-23 09:02:58 -07:00
void intel_sseu_set_info ( struct sseu_dev_info * sseu , u8 max_slices ,
u8 max_subslices , u8 max_eus_per_subslice )
{
sseu - > max_slices = max_slices ;
sseu - > max_subslices = max_subslices ;
sseu - > max_eus_per_subslice = max_eus_per_subslice ;
2019-08-23 09:02:59 -07:00
sseu - > ss_stride = GEN_SSEU_STRIDE ( sseu - > max_subslices ) ;
GEM_BUG_ON ( sseu - > ss_stride > GEN_MAX_SUBSLICE_STRIDE ) ;
2019-08-23 09:03:00 -07:00
sseu - > eu_stride = GEN_SSEU_STRIDE ( sseu - > max_eus_per_subslice ) ;
GEM_BUG_ON ( sseu - > eu_stride > GEN_MAX_EU_STRIDE ) ;
2019-08-23 09:02:58 -07:00
}
2019-05-24 08:40:21 -07:00
unsigned int
intel_sseu_subslice_total ( const struct sseu_dev_info * sseu )
{
unsigned int i , total = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( sseu - > subslice_mask ) ; i + + )
total + = hweight8 ( sseu - > subslice_mask [ i ] ) ;
return total ;
}
2019-08-23 09:03:07 -07:00
u32 intel_sseu_get_subslices ( const struct sseu_dev_info * sseu , u8 slice )
{
int i , offset = slice * sseu - > ss_stride ;
u32 mask = 0 ;
GEM_BUG_ON ( slice > = sseu - > max_slices ) ;
for ( i = 0 ; i < sseu - > ss_stride ; i + + )
mask | = ( u32 ) sseu - > subslice_mask [ offset + i ] < <
i * BITS_PER_BYTE ;
return mask ;
}
2019-08-23 09:03:02 -07:00
void intel_sseu_set_subslices ( struct sseu_dev_info * sseu , int slice ,
2019-08-23 09:03:03 -07:00
u32 ss_mask )
2019-08-23 09:03:02 -07:00
{
2019-08-23 09:03:03 -07:00
int offset = slice * sseu - > ss_stride ;
memcpy ( & sseu - > subslice_mask [ offset ] , & ss_mask , sseu - > ss_stride ) ;
2019-08-23 09:03:02 -07:00
}
2019-05-24 08:40:21 -07:00
unsigned int
intel_sseu_subslices_per_slice ( const struct sseu_dev_info * sseu , u8 slice )
{
2019-08-23 09:03:07 -07:00
return hweight32 ( intel_sseu_get_subslices ( sseu , slice ) ) ;
2019-05-24 08:40:21 -07:00
}
2019-04-24 10:51:34 +01:00
u32 intel_sseu_make_rpcs ( struct drm_i915_private * i915 ,
const struct intel_sseu * req_sseu )
{
const struct sseu_dev_info * sseu = & RUNTIME_INFO ( i915 ) - > sseu ;
bool subslice_pg = sseu - > has_subslice_pg ;
struct intel_sseu ctx_sseu ;
u8 slices , subslices ;
u32 rpcs = 0 ;
/*
* No explicit RPCS request is needed to ensure full
* slice / subslice / EU enablement prior to Gen9 .
*/
if ( INTEL_GEN ( i915 ) < 9 )
return 0 ;
/*
* If i915 / perf is active , we want a stable powergating configuration
* on the system .
*
* We could choose full enablement , but on ICL we know there are use
* cases which disable slices for functional , apart for performance
* reasons . So in this case we select a known stable subset .
*/
2019-08-06 16:30:02 -07:00
if ( ! i915 - > perf . exclusive_stream ) {
2019-04-24 10:51:34 +01:00
ctx_sseu = * req_sseu ;
} else {
ctx_sseu = intel_sseu_from_device_info ( sseu ) ;
if ( IS_GEN ( i915 , 11 ) ) {
/*
* We only need subslice count so it doesn ' t matter
* which ones we select - just turn off low bits in the
* amount of half of all available subslices per slice .
*/
ctx_sseu . subslice_mask =
~ ( ~ 0 < < ( hweight8 ( ctx_sseu . subslice_mask ) / 2 ) ) ;
ctx_sseu . slice_mask = 0x1 ;
}
}
slices = hweight8 ( ctx_sseu . slice_mask ) ;
subslices = hweight8 ( ctx_sseu . subslice_mask ) ;
/*
* Since the SScount bitfield in GEN8_R_PWR_CLK_STATE is only three bits
* wide and Icelake has up to eight subslices , specfial programming is
* needed in order to correctly enable all subslices .
*
* According to documentation software must consider the configuration
* as 2 x4x8 and hardware will translate this to 1 x8x8 .
*
* Furthemore , even though SScount is three bits , maximum documented
* value for it is four . From this some rules / restrictions follow :
*
* 1.
* If enabled subslice count is greater than four , two whole slices must
* be enabled instead .
*
* 2.
* When more than one slice is enabled , hardware ignores the subslice
* count altogether .
*
* From these restrictions it follows that it is not possible to enable
* a count of subslices between the SScount maximum of four restriction ,
* and the maximum available number on a particular SKU . Either all
* subslices are enabled , or a count between one and four on the first
* slice .
*/
if ( IS_GEN ( i915 , 11 ) & &
slices = = 1 & &
subslices > min_t ( u8 , 4 , hweight8 ( sseu - > subslice_mask [ 0 ] ) / 2 ) ) {
GEM_BUG_ON ( subslices & 1 ) ;
subslice_pg = false ;
slices * = 2 ;
}
/*
* Starting in Gen9 , render power gating can leave
* slice / subslice / EU in a partially enabled state . We
* must make an explicit request through RPCS for full
* enablement .
*/
if ( sseu - > has_slice_pg ) {
u32 mask , val = slices ;
if ( INTEL_GEN ( i915 ) > = 11 ) {
mask = GEN11_RPCS_S_CNT_MASK ;
val < < = GEN11_RPCS_S_CNT_SHIFT ;
} else {
mask = GEN8_RPCS_S_CNT_MASK ;
val < < = GEN8_RPCS_S_CNT_SHIFT ;
}
GEM_BUG_ON ( val & ~ mask ) ;
val & = mask ;
rpcs | = GEN8_RPCS_ENABLE | GEN8_RPCS_S_CNT_ENABLE | val ;
}
if ( subslice_pg ) {
u32 val = subslices ;
val < < = GEN8_RPCS_SS_CNT_SHIFT ;
GEM_BUG_ON ( val & ~ GEN8_RPCS_SS_CNT_MASK ) ;
val & = GEN8_RPCS_SS_CNT_MASK ;
rpcs | = GEN8_RPCS_ENABLE | GEN8_RPCS_SS_CNT_ENABLE | val ;
}
if ( sseu - > has_eu_pg ) {
u32 val ;
val = ctx_sseu . min_eus_per_subslice < < GEN8_RPCS_EU_MIN_SHIFT ;
GEM_BUG_ON ( val & ~ GEN8_RPCS_EU_MIN_MASK ) ;
val & = GEN8_RPCS_EU_MIN_MASK ;
rpcs | = val ;
val = ctx_sseu . max_eus_per_subslice < < GEN8_RPCS_EU_MAX_SHIFT ;
GEM_BUG_ON ( val & ~ GEN8_RPCS_EU_MAX_MASK ) ;
val & = GEN8_RPCS_EU_MAX_MASK ;
rpcs | = val ;
rpcs | = GEN8_RPCS_ENABLE ;
}
return rpcs ;
}