2014-05-14 17:02:16 +03:00
/*
* Copyright © 2014 Intel Corporation
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE .
*
* Authors :
* Mika Kuoppala < mika . kuoppala @ intel . com >
*
*/
# include "i915_drv.h"
# include "intel_renderstate.h"
static const struct intel_renderstate_rodata *
2016-05-06 15:40:21 +01:00
render_state_get_rodata ( const int gen )
2014-05-14 17:02:16 +03:00
{
switch ( gen ) {
case 6 :
return & gen6_null_state ;
case 7 :
return & gen7_null_state ;
case 8 :
return & gen8_null_state ;
2014-10-23 08:34:28 -07:00
case 9 :
return & gen9_null_state ;
2014-05-14 17:02:16 +03:00
}
return NULL ;
}
2016-05-06 15:40:21 +01:00
static int render_state_init ( struct render_state * so ,
struct drm_i915_private * dev_priv )
2014-05-14 17:02:16 +03:00
{
int ret ;
2016-05-06 15:40:21 +01:00
so - > gen = INTEL_GEN ( dev_priv ) ;
so - > rodata = render_state_get_rodata ( so - > gen ) ;
2014-06-10 11:23:33 +01:00
if ( so - > rodata = = NULL )
return 0 ;
if ( so - > rodata - > batch_items * 4 > 4096 )
2014-05-14 17:02:16 +03:00
return - EINVAL ;
2016-05-06 15:40:21 +01:00
so - > obj = i915_gem_object_create ( dev_priv - > dev , 4096 ) ;
2016-04-25 13:32:13 +01:00
if ( IS_ERR ( so - > obj ) )
return PTR_ERR ( so - > obj ) ;
2014-06-10 11:23:33 +01:00
ret = i915_gem_obj_ggtt_pin ( so - > obj , 4096 , 0 ) ;
if ( ret )
goto free_gem ;
so - > ggtt_offset = i915_gem_obj_ggtt_offset ( so - > obj ) ;
return 0 ;
free_gem :
drm_gem_object_unreference ( & so - > obj - > base ) ;
return ret ;
}
2015-07-20 10:46:10 +01:00
/*
* Macro to add commands to auxiliary batch .
* This macro only checks for page overflow before inserting the commands ,
* this is sufficient as the null state generator makes the final batch
* with two passes to build command and state separately . At this point
* the size of both are known and it compacts them by relocating the state
* right after the commands taking care of aligment so we should sufficient
* space below them for adding new commands .
*/
# define OUT_BATCH(batch, i, val) \
do { \
if ( WARN_ON ( ( i ) > = PAGE_SIZE / sizeof ( u32 ) ) ) { \
ret = - ENOSPC ; \
goto err_out ; \
} \
( batch ) [ ( i ) + + ] = ( val ) ; \
} while ( 0 )
2014-06-10 11:23:33 +01:00
static int render_state_setup ( struct render_state * so )
{
2016-06-03 06:34:33 +01:00
struct drm_device * dev = so - > obj - > base . dev ;
2014-06-10 11:23:33 +01:00
const struct intel_renderstate_rodata * rodata = so - > rodata ;
unsigned int i = 0 , reloc_index = 0 ;
struct page * page ;
u32 * d ;
int ret ;
2014-05-14 17:02:16 +03:00
ret = i915_gem_object_set_to_cpu_domain ( so - > obj , true ) ;
if ( ret )
return ret ;
2015-12-10 18:51:23 +00:00
page = i915_gem_object_get_dirty_page ( so - > obj , 0 ) ;
2014-06-10 11:23:33 +01:00
d = kmap ( page ) ;
2014-05-14 17:02:16 +03:00
while ( i < rodata - > batch_items ) {
u32 s = rodata - > batch [ i ] ;
2014-06-10 11:23:33 +01:00
if ( i * 4 = = rodata - > reloc [ reloc_index ] ) {
u64 r = s + so - > ggtt_offset ;
s = lower_32_bits ( r ) ;
if ( so - > gen > = 8 ) {
2014-05-14 17:02:16 +03:00
if ( i + 1 > = rodata - > batch_items | |
2015-07-17 17:08:51 +01:00
rodata - > batch [ i + 1 ] ! = 0 ) {
ret = - EINVAL ;
goto err_out ;
}
2014-05-14 17:02:16 +03:00
2014-06-10 11:23:33 +01:00
d [ i + + ] = s ;
s = upper_32_bits ( r ) ;
2014-05-14 17:02:16 +03:00
}
reloc_index + + ;
}
2014-06-10 11:23:33 +01:00
d [ i + + ] = s ;
2014-05-14 17:02:16 +03:00
}
2015-07-20 10:46:10 +01:00
while ( i % CACHELINE_DWORDS )
OUT_BATCH ( d , i , MI_NOOP ) ;
so - > aux_batch_offset = i * sizeof ( u32 ) ;
2016-06-03 06:34:33 +01:00
if ( HAS_POOLED_EU ( dev ) ) {
/*
* We always program 3 x6 pool config but depending upon which
* subslice is disabled HW drops down to appropriate config
* shown below .
*
* In the below table 2 x6 config always refers to
* fused - down version , native 2 x6 is not available and can
* be ignored
*
* SNo subslices config eu pool configuration
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* 1 3 subslices enabled ( 3 x6 ) - 0x00777000 ( 9 + 9 )
* 2 ss0 disabled ( 2 x6 ) - 0x00777000 ( 3 + 9 )
* 3 ss1 disabled ( 2 x6 ) - 0x00770000 ( 6 + 6 )
* 4 ss2 disabled ( 2 x6 ) - 0x00007000 ( 9 + 3 )
*/
u32 eu_pool_config = 0x00777000 ;
OUT_BATCH ( d , i , GEN9_MEDIA_POOL_STATE ) ;
OUT_BATCH ( d , i , GEN9_MEDIA_POOL_ENABLE ) ;
OUT_BATCH ( d , i , eu_pool_config ) ;
OUT_BATCH ( d , i , 0 ) ;
OUT_BATCH ( d , i , 0 ) ;
OUT_BATCH ( d , i , 0 ) ;
}
2015-07-20 10:46:10 +01:00
OUT_BATCH ( d , i , MI_BATCH_BUFFER_END ) ;
so - > aux_batch_size = ( i * sizeof ( u32 ) ) - so - > aux_batch_offset ;
/*
* Since we are sending length , we need to strictly conform to
* all requirements . For Gen2 this must be a multiple of 8.
*/
so - > aux_batch_size = ALIGN ( so - > aux_batch_size , 8 ) ;
2014-06-10 11:23:33 +01:00
kunmap ( page ) ;
2014-05-14 17:02:16 +03:00
ret = i915_gem_object_set_to_gtt_domain ( so - > obj , false ) ;
if ( ret )
return ret ;
2014-06-10 11:23:33 +01:00
if ( rodata - > reloc [ reloc_index ] ! = - 1 ) {
DRM_ERROR ( " only %d relocs resolved \n " , reloc_index ) ;
2014-05-14 17:02:16 +03:00
return - EINVAL ;
}
return 0 ;
2015-07-17 17:08:51 +01:00
err_out :
kunmap ( page ) ;
return ret ;
2014-05-14 17:02:16 +03:00
}
2015-07-20 10:46:10 +01:00
# undef OUT_BATCH
2014-08-21 11:40:54 +01:00
void i915_gem_render_state_fini ( struct render_state * so )
2014-06-10 11:23:33 +01:00
{
i915_gem_object_ggtt_unpin ( so - > obj ) ;
drm_gem_object_unreference ( & so - > obj - > base ) ;
}
2016-03-16 11:00:37 +00:00
int i915_gem_render_state_prepare ( struct intel_engine_cs * engine ,
2014-08-21 11:40:54 +01:00
struct render_state * so )
2014-05-14 17:02:16 +03:00
{
int ret ;
2016-03-16 11:00:37 +00:00
if ( WARN_ON ( engine - > id ! = RCS ) )
2014-05-21 19:01:06 +03:00
return - ENOENT ;
2016-05-06 15:40:21 +01:00
ret = render_state_init ( so , engine - > i915 ) ;
2014-06-10 11:23:33 +01:00
if ( ret )
return ret ;
2014-05-14 17:02:16 +03:00
2014-08-21 11:40:54 +01:00
if ( so - > rodata = = NULL )
2014-06-10 11:23:33 +01:00
return 0 ;
2014-05-14 17:02:16 +03:00
2014-08-21 11:40:54 +01:00
ret = render_state_setup ( so ) ;
if ( ret ) {
i915_gem_render_state_fini ( so ) ;
return ret ;
}
return 0 ;
}
2015-05-29 17:43:45 +01:00
int i915_gem_render_state_init ( struct drm_i915_gem_request * req )
2014-08-21 11:40:54 +01:00
{
struct render_state so ;
int ret ;
2016-03-16 11:00:38 +00:00
ret = i915_gem_render_state_prepare ( req - > engine , & so ) ;
2014-05-14 17:02:16 +03:00
if ( ret )
2014-08-21 11:40:54 +01:00
return ret ;
if ( so . rodata = = NULL )
return 0 ;
2014-05-14 17:02:16 +03:00
2016-03-16 11:00:38 +00:00
ret = req - > engine - > dispatch_execbuffer ( req , so . ggtt_offset ,
2015-05-29 17:43:45 +01:00
so . rodata - > batch_items * 4 ,
I915_DISPATCH_SECURE ) ;
2014-05-14 17:02:16 +03:00
if ( ret )
goto out ;
2015-07-20 10:46:10 +01:00
if ( so . aux_batch_size > 8 ) {
2016-03-16 11:00:38 +00:00
ret = req - > engine - > dispatch_execbuffer ( req ,
2015-07-20 10:46:10 +01:00
( so . ggtt_offset +
so . aux_batch_offset ) ,
so . aux_batch_size ,
I915_DISPATCH_SECURE ) ;
if ( ret )
goto out ;
}
2015-05-29 17:43:50 +01:00
i915_vma_move_to_active ( i915_gem_obj_to_ggtt ( so . obj ) , req ) ;
2014-05-14 17:02:16 +03:00
out :
2014-08-21 11:40:54 +01:00
i915_gem_render_state_fini ( & so ) ;
2014-05-14 17:02:16 +03:00
return ret ;
}