2019-10-08 17:01:14 +01:00
// SPDX-License-Identifier: MIT
/*
* Copyright © 2019 Intel Corporation
*/
# include "intel_memory_region.h"
# include "i915_drv.h"
2021-06-16 16:25:00 +01:00
# include "i915_ttm_buddy_manager.h"
2019-10-08 17:01:14 +01:00
2021-02-05 10:20:25 +00:00
static const struct {
u16 class ;
u16 instance ;
} intel_region_map [ ] = {
[ INTEL_REGION_SMEM ] = {
. class = INTEL_MEMORY_SYSTEM ,
. instance = 0 ,
} ,
[ INTEL_REGION_LMEM ] = {
. class = INTEL_MEMORY_LOCAL ,
. instance = 0 ,
} ,
2021-02-05 10:20:26 +00:00
[ INTEL_REGION_STOLEN_SMEM ] = {
. class = INTEL_MEMORY_STOLEN_SYSTEM ,
2021-02-05 10:20:25 +00:00
. instance = 0 ,
} ,
2021-04-21 11:46:55 +01:00
[ INTEL_REGION_STOLEN_LMEM ] = {
. class = INTEL_MEMORY_STOLEN_LOCAL ,
. instance = 0 ,
} ,
2019-10-18 10:07:50 +01:00
} ;
2021-04-29 11:30:53 +01:00
struct intel_memory_region *
intel_memory_region_lookup ( struct drm_i915_private * i915 ,
u16 class , u16 instance )
{
struct intel_memory_region * mr ;
int id ;
/* XXX: consider maybe converting to an rb tree at some point */
for_each_memory_region ( mr , i915 , id ) {
if ( mr - > type = = class & & mr - > instance = = instance )
return mr ;
}
return NULL ;
}
2020-01-04 19:10:42 +00:00
struct intel_memory_region *
intel_memory_region_by_type ( struct drm_i915_private * i915 ,
enum intel_memory_type mem_type )
{
struct intel_memory_region * mr ;
int id ;
for_each_memory_region ( mr , i915 , id )
if ( mr - > type = = mem_type )
return mr ;
return NULL ;
}
2021-06-02 10:38:08 +02:00
/**
* intel_memory_region_reserve - Reserve a memory range
* @ mem : The region for which we want to reserve a range .
* @ offset : Start of the range to reserve .
* @ size : The size of the range to reserve .
*
* Return : 0 on success , negative error code on failure .
*/
int intel_memory_region_reserve ( struct intel_memory_region * mem ,
resource_size_t offset ,
resource_size_t size )
2019-10-08 17:01:14 +01:00
{
2021-06-16 16:25:00 +01:00
struct ttm_resource_manager * man = mem - > region_private ;
2019-10-08 17:01:14 +01:00
2021-06-16 16:25:00 +01:00
GEM_BUG_ON ( mem - > is_range_manager ) ;
2019-10-08 17:01:14 +01:00
2021-06-16 16:25:00 +01:00
return i915_ttm_buddy_man_reserve ( man , offset , size ) ;
2021-01-27 13:14:13 +00:00
}
2021-08-19 10:34:19 +01:00
void intel_memory_region_debug ( struct intel_memory_region * mr ,
struct drm_printer * printer )
{
drm_printf ( printer , " %s: " , mr - > name ) ;
if ( mr - > region_private )
ttm_resource_manager_debug ( mr - > region_private , printer ) ;
else
drm_printf ( printer , " total:%pa, available:%pa bytes \n " ,
& mr - > total , & mr - > avail ) ;
}
2019-10-08 17:01:14 +01:00
struct intel_memory_region *
intel_memory_region_create ( struct drm_i915_private * i915 ,
resource_size_t start ,
resource_size_t size ,
resource_size_t min_page_size ,
resource_size_t io_start ,
2021-06-02 10:38:08 +02:00
u16 type ,
u16 instance ,
2019-10-08 17:01:14 +01:00
const struct intel_memory_region_ops * ops )
{
struct intel_memory_region * mem ;
int err ;
mem = kzalloc ( sizeof ( * mem ) , GFP_KERNEL ) ;
if ( ! mem )
return ERR_PTR ( - ENOMEM ) ;
mem - > i915 = i915 ;
mem - > region = ( struct resource ) DEFINE_RES_MEM ( start , size ) ;
mem - > io_start = io_start ;
mem - > min_page_size = min_page_size ;
mem - > ops = ops ;
2019-12-27 19:07:48 +05:30
mem - > total = size ;
mem - > avail = mem - > total ;
2021-06-02 10:38:08 +02:00
mem - > type = type ;
mem - > instance = instance ;
2019-10-08 17:01:14 +01:00
2019-10-08 17:01:16 +01:00
mutex_init ( & mem - > objects . lock ) ;
INIT_LIST_HEAD ( & mem - > objects . list ) ;
2019-10-08 17:01:14 +01:00
if ( ops - > init ) {
err = ops - > init ( mem ) ;
if ( err )
goto err_free ;
}
return mem ;
err_free :
kfree ( mem ) ;
return ERR_PTR ( err ) ;
}
2019-12-27 19:07:48 +05:30
void intel_memory_region_set_name ( struct intel_memory_region * mem ,
const char * fmt , . . . )
{
va_list ap ;
va_start ( ap , fmt ) ;
vsnprintf ( mem - > name , sizeof ( mem - > name ) , fmt , ap ) ;
va_end ( ap ) ;
}
2021-11-22 22:45:51 +01:00
void intel_memory_region_destroy ( struct intel_memory_region * mem )
2019-10-08 17:01:14 +01:00
{
2021-11-22 22:45:51 +01:00
int ret = 0 ;
2019-10-08 17:01:14 +01:00
if ( mem - > ops - > release )
2021-11-22 22:45:51 +01:00
ret = mem - > ops - > release ( mem ) ;
2019-10-08 17:01:14 +01:00
2021-11-22 22:45:51 +01:00
GEM_WARN_ON ( ! list_empty_careful ( & mem - > objects . list ) ) ;
2019-10-08 17:01:16 +01:00
mutex_destroy ( & mem - > objects . lock ) ;
2021-11-22 22:45:51 +01:00
if ( ! ret )
kfree ( mem ) ;
2019-10-08 17:01:14 +01:00
}
2019-10-26 21:20:32 +01:00
/* Global memory region registration -- only slight layer inversions! */
int intel_memory_regions_hw_probe ( struct drm_i915_private * i915 )
{
int err , i ;
for ( i = 0 ; i < ARRAY_SIZE ( i915 - > mm . regions ) ; i + + ) {
struct intel_memory_region * mem = ERR_PTR ( - ENODEV ) ;
2021-02-05 10:20:25 +00:00
u16 type , instance ;
2019-10-26 21:20:32 +01:00
if ( ! HAS_REGION ( i915 , BIT ( i ) ) )
continue ;
2021-02-05 10:20:25 +00:00
type = intel_region_map [ i ] . class ;
instance = intel_region_map [ i ] . instance ;
2019-10-26 21:20:32 +01:00
switch ( type ) {
case INTEL_MEMORY_SYSTEM :
2021-06-24 10:42:40 +02:00
if ( IS_DGFX ( i915 ) )
mem = i915_gem_ttm_system_setup ( i915 , type ,
instance ) ;
else
mem = i915_gem_shmem_setup ( i915 , type ,
instance ) ;
2019-10-26 21:20:32 +01:00
break ;
2021-04-21 11:46:55 +01:00
case INTEL_MEMORY_STOLEN_LOCAL :
2021-06-02 10:38:08 +02:00
mem = i915_gem_stolen_lmem_setup ( i915 , type , instance ) ;
2021-04-21 11:46:55 +01:00
if ( ! IS_ERR ( mem ) )
i915 - > mm . stolen_region = mem ;
break ;
2021-02-05 10:20:26 +00:00
case INTEL_MEMORY_STOLEN_SYSTEM :
2021-06-02 10:38:08 +02:00
mem = i915_gem_stolen_smem_setup ( i915 , type , instance ) ;
2021-04-21 11:46:55 +01:00
if ( ! IS_ERR ( mem ) )
i915 - > mm . stolen_region = mem ;
2019-10-26 21:20:32 +01:00
break ;
2021-01-27 13:14:10 +00:00
default :
continue ;
2019-10-26 21:20:32 +01:00
}
if ( IS_ERR ( mem ) ) {
err = PTR_ERR ( mem ) ;
2020-01-09 12:06:46 +03:00
drm_err ( & i915 - > drm ,
" Failed to setup region(%d) type=%d \n " ,
err , type ) ;
2019-10-26 21:20:32 +01:00
goto out_cleanup ;
}
2021-02-05 10:20:25 +00:00
mem - > id = i ;
2019-10-26 21:20:32 +01:00
i915 - > mm . regions [ i ] = mem ;
}
return 0 ;
out_cleanup :
intel_memory_regions_driver_release ( i915 ) ;
return err ;
}
void intel_memory_regions_driver_release ( struct drm_i915_private * i915 )
{
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( i915 - > mm . regions ) ; i + + ) {
struct intel_memory_region * region =
fetch_and_zero ( & i915 - > mm . regions [ i ] ) ;
if ( region )
2021-11-22 22:45:51 +01:00
intel_memory_region_destroy ( region ) ;
2019-10-26 21:20:32 +01:00
}
}
2019-10-08 17:01:14 +01:00
# if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
# include "selftests/intel_memory_region.c"
# include "selftests/mock_region.c"
# endif